<?php

namespace App\Services\Operations;

use App\Models\Client;
use App\Models\OperationTask;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Schema;

class DailyWorkflowService
{
    public function __construct(protected OperationCenterService $operations)
    {
    }

    public function board(array $filters = []): array
    {
        if (! Schema::hasTable('operation_tasks')) {
            return [
                'summary' => $this->emptySummary(),
                'lanes' => collect(),
                'today' => collect(),
                'overdue' => collect(),
                'upcoming' => collect(),
                'recent_completed' => collect(),
                'clients' => Client::orderBy('company_name')->get(),
                'users' => collect(),
            ];
        }

        $base = $this->filteredTaskQuery($filters);

        $openBase = OperationTask::query()->open();

        $summary = [
            'open_total' => (clone $openBase)->count(),
            'critical_open' => (clone $openBase)->where('priority', 'critical')->count(),
            'high_open' => (clone $openBase)->where('priority', 'high')->count(),
            'today' => (clone $openBase)->whereDate('due_at', today())->count(),
            'overdue' => (clone $openBase)->whereNotNull('due_at')->where('due_at', '<', now()->startOfDay())->count(),
            'unassigned' => (clone $openBase)->whereNull('assigned_to')->count(),
            'completed_today' => OperationTask::where('status', 'completed')->whereDate('completed_at', today())->count(),
        ];

        $tasks = $base->with(['client', 'assignee'])
            ->orderByRaw("FIELD(priority, 'critical', 'high', 'medium', 'low')")
            ->orderByRaw('CASE WHEN due_at IS NULL THEN 1 ELSE 0 END')
            ->orderBy('due_at')
            ->latest()
            ->get();

        $lanes = collect([
            'open' => $tasks->where('status', 'open')->values(),
            'in_progress' => $tasks->where('status', 'in_progress')->values(),
            'waiting' => $tasks->where('status', 'waiting')->values(),
            'completed' => $tasks->where('status', 'completed')->take(20)->values(),
        ]);

        return [
            'summary' => $summary,
            'lanes' => $lanes,
            'today' => OperationTask::with(['client', 'assignee'])->open()->whereDate('due_at', today())->orderBy('due_at')->get(),
            'overdue' => OperationTask::with(['client', 'assignee'])->open()->whereNotNull('due_at')->where('due_at', '<', now()->startOfDay())->orderBy('due_at')->get(),
            'upcoming' => OperationTask::with(['client', 'assignee'])->open()->whereBetween('due_at', [now()->endOfDay(), now()->addDays(7)->endOfDay()])->orderBy('due_at')->limit(20)->get(),
            'recent_completed' => OperationTask::with(['client', 'assignee'])->where('status', 'completed')->latest('completed_at')->limit(20)->get(),
            'clients' => Client::orderBy('company_name')->get(),
            'users' => class_exists(User::class) ? User::orderBy('name')->get() : collect(),
        ];
    }

    public function generateDailyTasks(array $options = []): array
    {
        if (! Schema::hasTable('operation_tasks')) {
            return ['created' => 0, 'skipped' => 0, 'message' => 'operation_tasks tablosu bulunamadı.'];
        }

        $cards = $this->operations->dashboard([
            'readiness' => $options['readiness'] ?? null,
            'platform' => $options['platform'] ?? null,
            'status' => 'active',
        ])['clients'] ?? collect();

        $created = 0;
        $skipped = 0;

        foreach ($cards as $card) {
            /** @var Client $client */
            $client = $card['client'];
            $actions = collect($card['actions'] ?? [])
                ->filter(fn (array $action) => in_array($action['priority'] ?? 'medium', ['critical', 'high', 'medium'], true));

            foreach ($actions as $action) {
                $exists = OperationTask::query()
                    ->where('client_id', $client->id)
                    ->where('title', $action['title'])
                    ->where('category', $action['category'] ?? 'operation')
                    ->whereIn('status', ['open', 'in_progress', 'waiting'])
                    ->exists();

                if ($exists) {
                    $skipped++;
                    continue;
                }

                OperationTask::create([
                    'client_id' => $client->id,
                    'title' => $action['title'],
                    'description' => $action['description'] ?? null,
                    'category' => $action['category'] ?? 'operation',
                    'priority' => $action['priority'] ?? 'medium',
                    'status' => 'open',
                    'source_type' => 'operation_center',
                    'source_id' => $client->id,
                    'due_at' => $this->dueAtForPriority($action['priority'] ?? 'medium'),
                    'meta' => [
                        'url' => $action['url'] ?? null,
                        'generated_by' => 'daily_workflow',
                        'readiness' => $card['readiness'] ?? null,
                    ],
                    'created_by' => auth()->id(),
                ]);

                $created++;
            }
        }

        return [
            'created' => $created,
            'skipped' => $skipped,
            'message' => $created.' görev oluşturuldu, '.$skipped.' görev zaten açıktı.',
        ];
    }

    public function filteredTaskQuery(array $filters)
    {
        return OperationTask::query()
            ->when(! empty($filters['q']), function ($query) use ($filters) {
                $term = '%'.trim($filters['q']).'%';
                $query->where(function ($sub) use ($term) {
                    $sub->where('title', 'like', $term)
                        ->orWhere('description', 'like', $term)
                        ->orWhereHas('client', fn ($client) => $client->where('company_name', 'like', $term));
                });
            })
            ->when(! empty($filters['client_id']), fn ($query) => $query->where('client_id', $filters['client_id']))
            ->when(! empty($filters['priority']), fn ($query) => $query->where('priority', $filters['priority']))
            ->when(! empty($filters['status']), fn ($query) => $query->where('status', $filters['status']))
            ->when(! empty($filters['category']), fn ($query) => $query->where('category', $filters['category']))
            ->when(! empty($filters['assigned_to']), function ($query) use ($filters) {
                if ($filters['assigned_to'] === 'none') {
                    $query->whereNull('assigned_to');
                } else {
                    $query->where('assigned_to', $filters['assigned_to']);
                }
            })
            ->when(! empty($filters['due']), function ($query) use ($filters) {
                match ($filters['due']) {
                    'today' => $query->whereDate('due_at', today()),
                    'overdue' => $query->whereNotNull('due_at')->where('due_at', '<', now()->startOfDay()),
                    'week' => $query->whereBetween('due_at', [now()->startOfDay(), now()->addDays(7)->endOfDay()]),
                    'none' => $query->whereNull('due_at'),
                    default => null,
                };
            });
    }

    public function statusLabels(): array
    {
        return [
            'open' => 'Açık',
            'in_progress' => 'İşlemde',
            'waiting' => 'Bekliyor',
            'completed' => 'Tamamlandı',
            'cancelled' => 'İptal',
        ];
    }

    public function priorityLabels(): array
    {
        return [
            'critical' => 'Kritik',
            'high' => 'Yüksek',
            'medium' => 'Orta',
            'low' => 'Düşük',
        ];
    }

    protected function dueAtForPriority(string $priority)
    {
        return match ($priority) {
            'critical' => now()->addHours(3),
            'high' => now()->addDay()->setTime(17, 0),
            'medium' => now()->addDays(2)->setTime(17, 0),
            default => now()->addDays(5)->setTime(17, 0),
        };
    }

    protected function emptySummary(): array
    {
        return [
            'open_total' => 0,
            'critical_open' => 0,
            'high_open' => 0,
            'today' => 0,
            'overdue' => 0,
            'unassigned' => 0,
            'completed_today' => 0,
        ];
    }
}
