<?php

namespace App\Http\Controllers\Api\V1;

use App\Helpers\ApiResponse;
use App\Helpers\CacheHelper;
use App\Http\Controllers\Controller;
use App\Models\Franchisee;
use App\Models\Program;
use App\Models\ProgramTranslation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\Response;

class CwProgramsController extends Controller
{
    public function storeProgramAgeGroup(Request $request)
    {
        $validator = Validator::make([
            'zoho_account_id' => $request->input('zoho_account_id', $request->query('zoho_account_id')),
            'age_groups' => $request->input('age_groups'),
        ], [
            'zoho_account_id' => ['nullable', 'string'],
            'age_groups' => ['required', 'array', 'min:1'],
            'age_groups.*.cw_program_id' => ['required', 'integer'],
            'age_groups.*.min_age' => ['required', 'integer', 'min:1'],
            'age_groups.*.max_age' => ['required', 'integer', 'min:1'],
        ]);

        if ($validator->fails()) {
            return ApiResponse::error($validator->errors()->first(), Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        $zohoAccountId = $request->input('zoho_account_id', $request->query('zoho_account_id'));
        $ageGroups = $request->input('age_groups', []);

        foreach ($ageGroups as $index => $group) {
            if ((int) $group['max_age'] < (int) $group['min_age']) {
                return ApiResponse::error("max_age must be greater than or equal to min_age at age_groups index {$index}.", Response::HTTP_UNPROCESSABLE_ENTITY);
            }
        }

        try {
            $franchisee = null;
            if (!empty($zohoAccountId)) {
                $franchisee = Franchisee::where('zoho_franchise_id', $zohoAccountId)->first();
                if (!$franchisee) {
                    return ApiResponse::error('Franchisee not found for the provided zoho_account_id.', Response::HTTP_NOT_FOUND);
                }
            }

            $updated = [];
            $notFound = [];
            $hasChanges = false;

            DB::beginTransaction();

            foreach ($ageGroups as $group) {
                $cwProgramId = (int) $group['cw_program_id'];
                $ageRange = ((int) $group['min_age']) . '-' . ((int) $group['max_age']);

                $programQuery = Program::where('cw_program_id', $cwProgramId)
                    ->where('is_global', $franchisee ? false : true);

                if ($franchisee) {
                    $programQuery->where('franchisee_id', $franchisee->id);
                } else {
                    $programQuery->whereNull('franchisee_id');
                }

                $programs = $programQuery->get();

                if ($programs->isEmpty() && $franchisee) {
                    $globalProgram = Program::where('cw_program_id', $cwProgramId)
                        ->where('is_global', true)
                        ->whereNull('franchisee_id')
                        ->first();

                    if (!$globalProgram) {
                        $notFound[] = [
                            'cw_program_id' => $cwProgramId,
                            'scope' => 'franchise',
                            'message' => 'No matching global program found to create franchise override.',
                        ];
                        continue;
                    }

                    $programs = collect([
                        Program::create([
                            'franchisee_id' => $franchisee->id,
                            'parent_program_id' => $globalProgram->id,
                            'cw_program_id' => $globalProgram->cw_program_id,
                            'slug' => $globalProgram->slug,
                            'header_image' => $globalProgram->header_image,
                            'program_icon' => $globalProgram->program_icon,
                            'color' => $globalProgram->color,
                            'background_color' => $globalProgram->background_color,
                            'is_enabled' => $globalProgram->is_enabled,
                            'is_global' => false,
                            'order_no' => $globalProgram->order_no,
                            'is_required_for_translation' => $globalProgram->is_required_for_translation,
                        ]),
                    ]);

                    $globalTranslations = ProgramTranslation::where('program_id', $globalProgram->id)
                        ->whereNull('franchisee_id')
                        ->get();

                    foreach ($globalTranslations as $gt) {
                        ProgramTranslation::updateOrCreate([
                            'program_id' => $programs->first()->id,
                            'franchisee_id' => $franchisee->id,
                            'language' => $gt->language,
                        ], [
                            'title' => $gt->title,
                            'sub_heading' => $gt->sub_heading,
                            'button_text' => $gt->button_text,
                            'age_range' => $ageRange,
                            'duration' => $gt->duration,
                            'no_of_lessons' => $gt->no_of_lessons,
                            'description' => $gt->description,
                            'age_text' => $gt->age_text,
                            'duration_text' => $gt->duration_text,
                            'lesson_duration_text' => $gt->lesson_duration_text,
                            'tag' => $gt->tag,
                            'program_details' => $gt->program_details,
                            'status' => $gt->status,
                            'adopted_from_global' => true,
                            'source_global_translation_id' => $gt->id,
                            'source_global_version' => $gt->version,
                            'last_local_edit_at' => null,
                        ]);
                    }

                    $hasChanges = true;
                }

                if ($programs->isEmpty()) {
                    $notFound[] = [
                        'cw_program_id' => $cwProgramId,
                        'scope' => $franchisee ? 'franchise' : 'global',
                        'message' => 'Program not found',
                    ];
                    continue;
                }

                foreach ($programs as $program) {
                    $translationQuery = ProgramTranslation::where('program_id', $program->id);
                    if ($franchisee) {
                        $translationQuery->where('franchisee_id', $franchisee->id);
                    } else {
                        $translationQuery->whereNull('franchisee_id');
                    }

                    $translations = $translationQuery->get();
                    foreach ($translations as $translation) {
                        if ($translation->age_range !== $ageRange) {
                            $translation->update(['age_range' => $ageRange]);
                            $hasChanges = true;
                        }

                        $updated[] = [
                            'program_id' => $program->id,
                            'translation_id' => $translation->id,
                            'cw_program_id' => $cwProgramId,
                            'language' => $translation->language,
                            'age_range' => $ageRange,
                            'scope' => $franchisee ? 'franchise' : 'global',
                        ];
                    }
                }
            }

            DB::commit();
            if ($hasChanges) {
                CacheHelper::forgetByTag('programs');
            }

            return ApiResponse::success([
                'franchisee_id' => $franchisee?->id,
                'zoho_account_id' => $zohoAccountId,
                'scope' => $franchisee ? 'franchise' : 'global',
                'updated_count' => count($updated),
                'not_found_count' => count($notFound),
                'updated' => $updated,
                'not_found' => $notFound,
            ], 'Program age groups updated successfully');
        } catch (\Throwable $e) {
            DB::rollBack();
            return ApiResponse::exception($e);
        }
    }

    public function storeCwProgram(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'cw_program_id' => ['required', 'integer'],
            'programs' => ['required', 'array', 'min:1'],
            'programs.*.language' => ['required', 'string', 'max:10'],
            'programs.*.slug' => ['required', 'string', 'max:191'],
            'programs.*.title' => ['required', 'string', 'max:191'],
            'programs.*.header_image' => ['nullable', 'string'],
            'programs.*.program_icon' => ['nullable', 'string', 'max:191'],
            'programs.*.color' => ['nullable', 'string', 'max:191'],
            'programs.*.background_color' => ['nullable', 'string', 'max:191'],
            'programs.*.button_text' => ['nullable', 'string', 'max:191'],
            'programs.*.age_range' => ['nullable', 'string', 'max:191'],
            'programs.*.duration' => ['nullable', 'string', 'max:191'],
            'programs.*.is_enabled' => ['nullable', 'boolean'],
            'programs.*.order_no' => ['nullable', 'integer'],
            'programs.*.sub_heading' => ['nullable', 'string', 'max:191'],
            'programs.*.no_of_lessons' => ['nullable', 'string', 'max:191'],
            'programs.*.description' => ['nullable', 'string'],
            'programs.*.program_details' => ['nullable', 'array'],
            'programs.*.age_text' => ['nullable', 'string', 'max:191'],
            'programs.*.duration_text' => ['nullable', 'string', 'max:191'],
            'programs.*.lesson_duration_text' => ['nullable', 'string', 'max:191'],
            'programs.*.tag' => ['nullable', 'string', 'max:191'],
            'programs.*.status' => ['nullable', 'in:draft,publish'],
        ]);

        if ($validator->fails()) {
            return ApiResponse::error($validator->errors()->first(), Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        $cwProgramId = (int) $request->cw_program_id;
        $items = $request->programs;
        $base = $items[0];

        try {
            DB::beginTransaction();

            $program = Program::firstOrCreate([
                'cw_program_id' => $cwProgramId,
                'franchisee_id' => null,
                'is_global' => true,
            ], [
                'parent_program_id' => null,
                'slug' => $base['slug'],
                'header_image' => $base['header_image'] ?? null,
                'program_icon' => $base['program_icon'] ?? null,
                'color' => $base['color'] ?? null,
                'background_color' => $base['background_color'] ?? null,
                'is_enabled' => $base['is_enabled'] ?? true,
                'order_no' => $base['order_no'] ?? 1,
                'is_required_for_translation' => false,
            ]);

            $program->update([
                'slug' => $base['slug'],
                'header_image' => $base['header_image'] ?? $program->header_image,
                'program_icon' => $base['program_icon'] ?? $program->program_icon,
                'color' => $base['color'] ?? $program->color,
                'background_color' => $base['background_color'] ?? $program->background_color,
                'is_enabled' => $base['is_enabled'] ?? $program->is_enabled,
                'order_no' => $base['order_no'] ?? $program->order_no,
            ]);

            $created = [];
            $updated = [];
            $hasChanges = false;

            foreach ($items as $item) {
                $translation = ProgramTranslation::where('program_id', $program->id)
                    ->whereNull('franchisee_id')
                    ->where('language', strtolower($item['language']))
                    ->first();

                $payload = [
                    'title' => $item['title'],
                    'sub_heading' => $item['sub_heading'] ?? null,
                    'button_text' => $item['button_text'] ?? null,
                    'age_range' => $item['age_range'] ?? null,
                    'duration' => $item['duration'] ?? null,
                    'no_of_lessons' => $item['no_of_lessons'] ?? null,
                    'description' => $item['description'] ?? null,
                    'age_text' => $item['age_text'] ?? null,
                    'duration_text' => $item['duration_text'] ?? null,
                    'lesson_duration_text' => $item['lesson_duration_text'] ?? null,
                    'tag' => $item['tag'] ?? null,
                    'program_details' => $item['program_details'] ?? null,
                    'status' => strtolower((string) ($item['status'] ?? 'draft')),
                ];

                if ($translation) {
                    $translation->fill($payload);
                    if ($translation->isDirty()) {
                        if (in_array($translation->status, ['publish', 'published', 'active'], true)) {
                            $translation->version = ((int) $translation->version) + 1;
                        }
                        $translation->save();
                        $hasChanges = true;
                    }

                    $updated[] = [
                        'id' => $translation->id,
                        'program_id' => $program->id,
                        'language' => $translation->language,
                        'action' => 'updated',
                    ];
                    continue;
                }

                $translation = ProgramTranslation::create(array_merge($payload, [
                    'program_id' => $program->id,
                    'franchisee_id' => null,
                    'language' => strtolower($item['language']),
                    'version' => 1,
                ]));

                $created[] = [
                    'id' => $translation->id,
                    'program_id' => $program->id,
                    'language' => $translation->language,
                    'action' => 'created',
                ];
                $hasChanges = true;
            }

            DB::commit();
            if ($hasChanges) {
                CacheHelper::forgetByTag('programs');
            }

            return ApiResponse::success([
                'cw_program_id' => $cwProgramId,
                'program_id' => $program->id,
                'created_count' => count($created),
                'updated_count' => count($updated),
                'created' => $created,
                'updated' => $updated,
            ], 'CW programs stored successfully');
        } catch (\Throwable $e) {
            DB::rollBack();
            return ApiResponse::exception($e);
        }
    }

    public function deleteCwProgram($cw_program_id)
    {
        if (!is_numeric($cw_program_id)) {
            return ApiResponse::error('Invalid cw_program_id.', Response::HTTP_UNPROCESSABLE_ENTITY);
        }

        try {
            DB::beginTransaction();

            $programs = Program::where('cw_program_id', (int) $cw_program_id)->get();
            if ($programs->isEmpty()) {
                return ApiResponse::error('No program found for the given cw_program_id.', Response::HTTP_NOT_FOUND);
            }

            $deleted = [];
            foreach ($programs as $program) {
                $deleted[] = [
                    'id' => $program->id,
                    'cw_program_id' => $program->cw_program_id,
                    'franchisee_id' => $program->franchisee_id,
                    'is_global' => $program->is_global,
                ];
                $program->delete();
            }

            DB::commit();
            CacheHelper::forgetByTag('programs');

            return ApiResponse::success([
                'cw_program_id' => (int) $cw_program_id,
                'deleted_count' => count($deleted),
                'deleted' => $deleted,
            ], 'CW program deleted successfully');
        } catch (\Throwable $e) {
            DB::rollBack();
            return ApiResponse::exception($e);
        }
    }
}
