<?php

namespace App\Services;

use App\Models\FormTemplate;
use App\Models\FormInstance;
use App\Models\FormInstanceValue;
use App\Models\FormInstanceActSection;
use App\Models\StatutoryMaster;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class FormInstanceGeneratorService
{
    public function generate(): array
    {
        $now = Carbon::now();

        $stats = [
            'templates_processed' => 0,
            'instances_created' => 0,
            'skipped_duplicates' => 0,
            'skipped_no_periodicity' => 0,
            'skipped_not_due' => 0,
        ];

        $templates = FormTemplate::with(['fields', 'statutory_act'])
    ->where('is_active', 1)
    ->distinct('form_templates.id')
    ->get();


        foreach ($templates as $template) {
            $stats['templates_processed']++;

            if ($template->statutory_act->count() > 0) {
                $result = $this->processStatutoryTemplate($template, $now);
                $this->mergeStats($stats, $result);
                continue;
            }

            // NON-STATUTORY
            if (empty($template->periodicity)) {
                $stats['skipped_no_periodicity']++;
                continue;
            }

            if (!$this->shouldRunThisMonth($template->periodicity, $now)) {
                $stats['skipped_not_due']++;
                continue;
            }

            $created = $this->createInstance($template, []);
            $created ? $stats['instances_created']++ : $stats['skipped_duplicates']++;
        }

        return $stats;
    }

    /* =========================================================
       STATUTORY HANDLING (ONE FORM, MANY ACTS)
    ========================================================== */

    protected function processStatutoryTemplate(FormTemplate $template, Carbon $now): array
    {
        $stats = [
            'instances_created' => 0,
            'skipped_duplicates' => 0,
            'skipped_not_due' => 0,
        ];

        $acts = StatutoryMaster::whereIn(
                'id',
                $template->statutory_act->pluck('statutory_id')
            )
            ->with('statutory_sections')
            ->get();

        $dueActs = [];

        foreach ($acts as $act) {
            if (!$act->periodicity) {
                continue;
            }

            if (!$this->shouldRunThisMonth($act->periodicity, $now)) {
                $stats['skipped_not_due']++;
                continue;
            }

            $dueActs[] = $act;
        }

        if (empty($dueActs)) {
            return $stats;
        }

        $created = $this->createInstance($template, $dueActs);
        $created ? $stats['instances_created']++ : $stats['skipped_duplicates']++;

        return $stats;
    }

    /* =========================================================
       INSTANCE CREATION (IDEMPOTENT)
    ========================================================== */

    protected function createInstance(FormTemplate $template, array $acts): bool
    {
        return DB::transaction(function () use ($template, $acts) {

            $period = Carbon::now()->format('Y-m');

            // ✅ IDENTITY GUARANTEE
            $instance = FormInstance::firstOrCreate(
                [
                    'form_template_id' => $template->id,
                    'client_id'        => $template->client_id,
                    'branch_id'        => $template->client_branch_id,
                    'period'           => $period,
                ],
                [
                    'current_status' => 'PENDING',
                    'due_date'       => null,
                    'assigned_to'    => null,
                    'reviewer_id'    => null,
                    'risk_level'     => null,
                ]
            );

            // If already existed → do NOT count as new
            $isNew = $instance->wasRecentlyCreated;

            // Ensure form_instance_values exist only once
            if ($isNew) {
                foreach ($template->fields as $field) {
                    FormInstanceValue::create([
                        'form_instance_id' => $instance->id,
                        'form_field_id'    => $field->id,
                        'field_value'      => null,
                    ]);
                }
            }

            // Ensure act sections are not duplicated
            foreach ($acts as $act) {
                foreach ($act->statutory_sections as $section) {
                    FormInstanceActSection::firstOrCreate([
                        'form_instance_id' => $instance->id,
                        'act_id'           => $act->id,
                        'sections_id'      => $section->id,
                    ], [
                        'remarks' => null,
                        'status'  => 'PENDING',
                        'attachment' => null,
                    ]);
                }
            }

            return $isNew;
        });
    }

    /* =========================================================
       PERIODICITY HELPERS
    ========================================================== */

    protected function shouldRunThisMonth(string $periodicity, Carbon $now): bool
    {
        return match (strtolower($periodicity)) {
            'one-time', 'monthly' => true,
            'quarterly' => in_array($now->month, [1, 4, 7, 10]),
            'half yearly', 'half-yearly' => in_array($now->month, [1, 7]),
            'annual', 'yearly' => $now->month === 1,
            default => false,
        };
    }

    protected function mergeStats(array &$main, array $partial): void
    {
        foreach ($partial as $key => $value) {
            if (isset($main[$key])) {
                $main[$key] += $value;
            }
        }
    }
}
