<?php

namespace App\Http\Controllers\Admin;

use App\Helpers\ApiResponse;
use App\Helpers\CacheHelper;
use App\Http\Controllers\Controller;
use App\Models\AdditionalActivity;
use App\Models\AuditLog;
use App\Models\Form;
use App\Models\FormSubmission;
use App\Models\Franchisee;
use App\Models\FranchiseAddress;
use App\Models\Notification;
use App\Models\Page;
use App\Models\PageTranslationSubmission;
use App\Models\Payment;
use App\Models\PaymentInvoice;
use App\Models\Program;
use App\Models\Setting;
use App\Models\Teacher;
use App\Models\Testimonial;
use App\Models\TranslatedPage;
use App\Models\User;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpFoundation\Response;

class FranchiseeController extends Controller
{
    public function index(Request $request)
    {
        $auth = Auth::user();

        if (!$auth) {
            return ApiResponse::error("Unauthorized", Response::HTTP_UNAUTHORIZED);
        }
        try {
            $perPage = $request->get('per_page', 10);
            $sortBy = $request->get('sort_by', 'created_at');
            $sortOrder = $request->get('sort_order', 'desc');
            $search = $request->get('search', '');
            $cacheKey = 'franchisees_' . md5(json_encode([
                'search' => $search,
                'sort_by' => $sortBy,
                'sort_order' => $sortOrder,
                'per_page' => $perPage,
                'page' => $request->get('page', 1),
            ]));
            $franchisees = CacheHelper::rememberByTag('franchisees', $cacheKey, function () use ($auth, $sortBy, $sortOrder, $search, $perPage) {

                return Franchisee::query()
                    ->with('groups:id,name') // Load only group id and name
                    ->when($search, function ($query, $search) {
                        $query->where('name', 'like', "%{$search}%")
                            ->orWhere('email', 'like', "%{$search}%")
                            ->orWhere('owner_name', 'like', "%{$search}%")
                            ->orWhere('franchise_domain', 'like', "%{$search}%");
                    })
                    ->when($sortBy, function ($query, $sortBy) use ($sortOrder) {
                        $allowedColumns = ['id', 'name', 'email', 'owner_name', 'franchise_domain', 'status', 'created_at'];
                        if (in_array($sortBy, $allowedColumns)) {
                            $query->orderBy($sortBy, $sortOrder === 'asc' ? 'asc' : 'desc');
                        } else {
                            $query->orderBy('created_at', 'desc');
                        }
                    })
                    ->paginate($perPage);

            });
            return ApiResponse::success($franchisees);
        } catch (\Throwable $e) {
            return ApiResponse::exception($e);
        }
    }

    public function store(Request $request)
    {
        $auth = Auth::user();
        // Only super admin can create franchisee
        if ($request->user()->role !== 'super_admin') {
            return ApiResponse::error('Only super admin can create franchisee.', Response::HTTP_FORBIDDEN);
        }
        try {
            $validated = $request->validate([
                'name' => 'required|string',
                'franchise_domain' => 'required|string|unique:franchisees,franchise_domain',
                'is_custom_domain' => 'boolean',
                'owner_name' => 'required|string',
                'email' => [
                    'required',
                    'email',
                    function ($attribute, $value, $fail) {
                        if (Franchisee::whereRaw('LOWER(email) = ?', [strtolower($value)])->exists()) {
                            $fail('The email has already been taken.');
                        }
                    },
                ],
                'phone' => 'required|string',
                'status' => ['required', Rule::in(['active', 'disabled'])],
                'language' => 'string|in:en,hi,fr,de',
            ]);

            // Create franchisee and corresponding user in a single transaction
            $validated['email'] = strtolower($validated['email']);

            $franchisee = DB::transaction(function () use ($validated) {
                $fr = Franchisee::create($validated);
                // Create default franchise admin user
                User::create([
                    'franchisee_id' => $fr->id,
                    'name' => $fr->owner_name,
                    'email' => $fr->email,
                    'password' => Hash::make('Admin@12345'),
                    'role' => 'franchise_admin',
                ]);
                return $fr;
            });
            CacheHelper::forgetByTag('franchisees');
            return ApiResponse::success($franchisee, 'Franchisee and user created successfully.', Response::HTTP_CREATED);
        } catch (\Throwable $e) {
            return ApiResponse::exception($e);
        }
    }

    public function show(string $franchiseeId)
    {

        try {
            $franchisee = Franchisee::with('groups:id,name,description')->where('id', $franchiseeId)->firstOrFail();
            return ApiResponse::success($franchisee);
        } catch (\Throwable $e) {
            return ApiResponse::exception($e);
        }
    }

    public function update(Request $request, string $franchiseeId)
    {
        $auth = Auth::user();
        // Only super admin can update franchisees
        if ($request->user()->role !== 'super_admin') {
            return ApiResponse::error('Only super admin can update franchisee.', Response::HTTP_FORBIDDEN);
        }
        try {
            $franchisee = Franchisee::where('id', $franchiseeId)->firstOrFail();

            $validated = $request->validate([
                'name' => 'sometimes|required|string',
                'franchise_domain' => [
                    'sometimes',
                    'required',
                    'string',
                    Rule::unique('franchisees', 'franchise_domain')->ignore($franchisee->id),
                ],
                'is_custom_domain' => 'boolean',
                'owner_name' => 'sometimes|required|string',
                'email' => [
                    'sometimes',
                    'required',
                    'email',
                    function ($attribute, $value, $fail) use ($franchisee) {
                        if (Franchisee::whereRaw('LOWER(email) = ?', [strtolower($value)])->where('id', '!=', $franchisee->id)->exists()) {
                            $fail('The email has already been taken.');
                        }
                    },
                ],
                'phone' => 'sometimes|required|string',
                'status' => ['sometimes', 'required', Rule::in(['active', 'disabled'])],
                'is_website_approved' => 'boolean',
                'language' => 'string|in:en,hi,fr,de',
                'group_ids' => 'sometimes|array',
                'group_ids.*' => 'string|exists:franchisee_groups,id',
            ]);

            Log::debug('Franchisee Update Data:', ['validated' => $validated, 'id' => $franchiseeId]);

            if (isset($validated['email'])) {
                $validated['email'] = strtolower($validated['email']);
            }

            $franchisee->update($validated);

            // Keep franchise_addresses.status in sync so a disabled franchisee's
            // location stops appearing in the public active-latlng listing.
            if (isset($validated['status'])) {
                FranchiseAddress::where('zoho_franchise_id', $franchisee->zoho_franchise_id)
                    ->update(['status' => $validated['status']]);
            }

            // Handle group assignment if group_ids is provided
            if (isset($validated['group_ids'])) {
                $franchisee->groups()->sync($validated['group_ids']);
            }

            // Update default franchise admin user to reflect any owner_name or email changes
            User::where('franchisee_id', $franchisee->id)
                ->where('role', 'franchise_admin')
                ->update([
                    'name' => $franchisee->owner_name,
                ]);

            if (isset($validated['email'])) {
                // Find the user first to see if we're actually changing the email
                $adminUser = User::where('franchisee_id', $franchisee->id)
                    ->where('role', 'franchise_admin')
                    ->first();

                if ($adminUser && strtolower($adminUser->email) !== strtolower($validated['email'])) {
                    $adminUser->update(['email' => $validated['email']]);
                }
            }

            CacheHelper::clearAllCache();
            return ApiResponse::success($franchisee, 'Franchisee and user updated successfully.');
        } catch (\Throwable $e) {
            Log::error('Franchisee Update Error:', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'request' => $request->all()
            ]);
            return ApiResponse::exception($e);
        }
    }

    public function destroy(string $franchiseeId)
    {
        $auth = Auth::user();
        // Only super admin can delete franchisees
        if ($auth->role !== 'super_admin') {
            return ApiResponse::error('Only super admin can delete franchisee.', Response::HTTP_FORBIDDEN);
        }
        try {
            // Delete franchisee and its admin user in a transaction
            DB::transaction(function () use ($franchiseeId, $auth) {
                User::where('franchisee_id', $franchiseeId)
                    //->where('role', 'franchise_admin')
                    ->delete();

                // Soft Delete by Franchisee id
                Page::where('franchisee_id', $franchiseeId)->delete();
                PageTranslationSubmission::where('franchisee_id', $franchiseeId)->delete();
                TranslatedPage::where('franchisee_id', $franchiseeId)->delete();
                Program::where('franchisee_id', $franchiseeId)->delete();
                Form::where('franchisee_id', $franchiseeId)->delete();
                FormSubmission::where('franchisee_id', $franchiseeId)->delete();
                Testimonial::where('franchisee_id', $franchiseeId)->delete();
                Teacher::where('franchisee_id', $franchiseeId)->delete();
                AdditionalActivity::where('franchisee_id', $franchiseeId)->delete();
                Setting::where('franchisee_id', $franchiseeId)->delete();
                Payment::where('franchisee_id', $franchiseeId)->delete();
                PaymentInvoice::where('franchisee_id', $franchiseeId)->delete();
                Notification::where('franchisee_id', $franchiseeId)->delete();
                AuditLog::where('franchisee_id', $franchiseeId)->delete();

                // Delete the franchisee
                $fr = Franchisee::where('id', $franchiseeId)->firstOrFail();
                $fr->delete();
            });
            CacheHelper::forgetByTag('franchisees');
            return ApiResponse::success(null, 'Franchisee deleted successfully.');
        } catch (\Throwable $e) {
            return ApiResponse::exception($e);
        }
    }

    public function permanentDelete(string $franchiseeId)
    {
        $auth = Auth::user();

        // Only super admin can delete franchisees
        if ($auth->role !== 'super_admin') {
            return ApiResponse::error(
                'Only super admin can delete franchisee.',
                Response::HTTP_FORBIDDEN
            );
        }

        try {

            DB::transaction(function () use ($franchiseeId) {

                // Permanently delete admin users
                User::where('franchisee_id', $franchiseeId)
                    ->forceDelete();

                // Permanently delete related data
                Page::where('franchisee_id', $franchiseeId)->forceDelete();
                PageTranslationSubmission::where('franchisee_id', $franchiseeId)->forceDelete();
                TranslatedPage::where('franchisee_id', $franchiseeId)->forceDelete();
                Program::where('franchisee_id', $franchiseeId)->forceDelete();
                Form::where('franchisee_id', $franchiseeId)->forceDelete();
                FormSubmission::where('franchisee_id', $franchiseeId)->forceDelete();
                Testimonial::where('franchisee_id', $franchiseeId)->forceDelete();
                Teacher::where('franchisee_id', $franchiseeId)->forceDelete();
                AdditionalActivity::where('franchisee_id', $franchiseeId)->forceDelete();
                Setting::where('franchisee_id', $franchiseeId)->forceDelete();
                Payment::where('franchisee_id', $franchiseeId)->forceDelete();
                PaymentInvoice::where('franchisee_id', $franchiseeId)->forceDelete();
                Notification::where('franchisee_id', $franchiseeId)->forceDelete();
                AuditLog::where('franchisee_id', $franchiseeId)->forceDelete();

                // Permanently delete franchisee
                $franchisee = Franchisee::where('id', $franchiseeId)->firstOrFail();
                $franchisee->forceDelete();
            });

            CacheHelper::forgetByTag('franchisees');

            return ApiResponse::success(null, 'Franchisee permanently deleted successfully.');

        } catch (\Throwable $e) {
            return ApiResponse::exception($e);
        }
    }
}
