<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;

class SchoolController extends Controller
{
    public function index(): Response
    {
        $schools = DB::table('schools')
            ->leftJoin('users as owner', function ($join): void {
                $join->on('owner.school_id', '=', 'schools.id')->where('owner.role_key', 'owner');
            })
            ->leftJoin('sms_wallets', 'sms_wallets.school_id', '=', 'schools.id')
            ->leftJoin('licenses', function ($join): void {
                $join->on('licenses.school_id', '=', 'schools.id')->where('licenses.status', 'active');
            })
            ->orderByDesc('schools.created_at')
            ->limit(200)
            ->get([
                'schools.id',
                'schools.name_fa',
                'schools.school_code',
                'schools.city',
                'schools.status',
                'owner.username as owner_username',
                'owner.first_name as owner_first_name',
                'owner.last_name as owner_last_name',
                'sms_wallets.balance as sms_balance',
                'licenses.expires_at',
            ]);

        return Inertia::render('SuperAdmin/Schools', [
            'metrics' => [
                'activeSchools' => DB::table('schools')->where('status', 'active')->count(),
                'totalStudents' => DB::table('students')->count(),
                'totalTeachers' => DB::table('teachers')->count(),
            ],
            'schools' => $schools->map(fn ($school): array => [
                'id' => (int) $school->id,
                'name' => $school->name_fa,
                'code' => $school->school_code,
                'city' => $school->city ?? '—',
                'status' => $school->status,
                'owner' => $school->owner_username
                    ? trim(($school->owner_first_name ?? '').' '.($school->owner_last_name ?? ''))." ({$school->owner_username})"
                    : '—',
                'smsBalance' => (int) ($school->sms_balance ?? 0),
                'expiresAt' => $school->expires_at ? $this->jalaliDate($school->expires_at) : '—',
            ])->values(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'school_name' => ['required', 'string', 'max:190'],
            'school_code' => ['required', 'string', 'max:80', 'unique:schools,school_code'],
            'city' => ['nullable', 'string', 'max:120'],
            'province' => ['nullable', 'string', 'max:120'],
            'phone' => ['nullable', 'string', 'max:30'],
            'owner_username' => ['required', 'string', 'max:120', 'unique:users,username'],
            'owner_first_name' => ['required', 'string', 'max:120'],
            'owner_last_name' => ['required', 'string', 'max:120'],
            'owner_mobile' => ['nullable', 'string', 'max:30'],
            'license_expires' => ['required', 'date'],
        ]);

        $tempPassword = Str::random(12);

        DB::transaction(function () use ($data, $tempPassword): void {
            $schoolId = DB::table('schools')->insertGetId([
                'name_fa' => $data['school_name'],
                'school_code' => $data['school_code'],
                'city' => $data['city'] ?? null,
                'province' => $data['province'] ?? null,
                'phone' => $data['phone'] ?? null,
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            $ownerId = DB::table('users')->insertGetId([
                'school_id' => $schoolId,
                'username' => $data['owner_username'],
                'password' => Hash::make($tempPassword),
                'first_name' => $data['owner_first_name'],
                'last_name' => $data['owner_last_name'],
                'mobile' => $data['owner_mobile'] ?? null,
                'role_key' => 'owner',
                'status' => 'active',
                'must_change_password' => true,
                'must_complete_profile' => false,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            DB::table('licenses')->insert([
                'school_id' => $schoolId,
                'starts_at' => now()->toDateString(),
                'expires_at' => $data['license_expires'],
                'status' => 'active',
                'created_by' => request()->user()?->id,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            DB::table('sms_wallets')->insert([
                'school_id' => $schoolId,
                'balance' => 0,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        });

        return redirect()->route('super-admin.schools')
            ->with('temp_password', "مدرسه ساخته شد. رمز موقت owner «{$data['owner_username']}»: {$tempPassword}");
    }

    public function toggleStatus(Request $request, int $id): RedirectResponse
    {
        $school = DB::table('schools')->where('id', $id)->first();
        abort_unless($school, 404);

        $newStatus = $school->status === 'active' ? 'inactive' : 'active';
        DB::table('schools')->where('id', $id)->update(['status' => $newStatus, 'updated_at' => now()]);

        return redirect()->route('super-admin.schools')->with('success', 'وضعیت مدرسه تغییر کرد.');
    }

    public function manageModules(int $id): Response
    {
        $school = DB::table('schools')->where('id', $id)->first(['id', 'name_fa', 'school_code']);
        abort_unless($school, 404);

        $allModules = DB::table('modules')
            ->where('is_sellable', true)
            ->where('status', 'active')
            ->orderBy('key_name')
            ->get(['id', 'key_name', 'name_fa']);

        $enabledModuleIds = DB::table('school_modules')
            ->where('school_id', $id)
            ->where('enabled', true)
            ->pluck('module_id');

        return Inertia::render('SuperAdmin/SchoolModules', [
            'school' => [
                'id' => (int) $school->id,
                'name' => $school->name_fa,
                'code' => $school->school_code,
            ],
            'modules' => $allModules->map(fn ($module): array => [
                'id' => (int) $module->id,
                'key' => $module->key_name,
                'label' => $module->name_fa,
                'enabled' => $enabledModuleIds->contains($module->id),
            ])->values(),
        ]);
    }

    public function renewLicense(Request $request, int $id): RedirectResponse
    {
        $school = DB::table('schools')->where('id', $id)->first();
        abort_unless($school, 404);

        $data = $request->validate([
            'expires_at' => ['required', 'date', 'after:today'],
        ]);

        $existing = DB::table('licenses')->where('school_id', $id)->where('status', 'active')->first();

        if ($existing) {
            DB::table('licenses')->where('id', $existing->id)->update([
                'expires_at' => $data['expires_at'],
                'updated_at' => now(),
            ]);
        } else {
            DB::table('licenses')->insert([
                'school_id' => $id,
                'starts_at' => now()->toDateString(),
                'expires_at' => $data['expires_at'],
                'status' => 'active',
                'created_by' => $request->user()?->id,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }

        return redirect()->route('super-admin.schools')->with('success', "مجوز مدرسه «{$school->name_fa}» تا {$data['expires_at']} تمدید شد.");
    }

    public function chargeSmsWallet(Request $request, int $id): RedirectResponse
    {
        $school = DB::table('schools')->where('id', $id)->first();
        abort_unless($school, 404);

        $data = $request->validate([
            'amount' => ['required', 'integer', 'min:1', 'max:10000000'],
            'description' => ['nullable', 'string', 'max:255'],
        ]);

        DB::transaction(function () use ($id, $data, $request): void {
            $wallet = DB::table('sms_wallets')->where('school_id', $id)->first();
            $balanceBefore = (int) ($wallet->balance ?? 0);
            $balanceAfter = $balanceBefore + $data['amount'];

            if ($wallet) {
                DB::table('sms_wallets')->where('school_id', $id)->update([
                    'balance' => $balanceAfter,
                    'total_charged' => (int) ($wallet->total_charged ?? 0) + $data['amount'],
                    'updated_at' => now(),
                ]);
            } else {
                DB::table('sms_wallets')->insert([
                    'school_id' => $id,
                    'balance' => $balanceAfter,
                    'total_charged' => $data['amount'],
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }

            DB::table('sms_wallet_transactions')->insert([
                'school_id' => $id,
                'type' => 'charge',
                'amount' => $data['amount'],
                'balance_before' => $balanceBefore,
                'balance_after' => $balanceAfter,
                'description' => $data['description'] ?? 'شارژ دستی توسط Super Admin',
                'created_by' => $request->user()?->id,
                'created_at' => now(),
            ]);
        });

        return redirect()->route('super-admin.schools')->with('success', "کیف پول SMS مدرسه «{$school->name_fa}» به مقدار {$data['amount']} واحد شارژ شد.");
    }

    public function toggleModule(Request $request, int $id, int $moduleId): RedirectResponse
    {
        $school = DB::table('schools')->where('id', $id)->first();
        abort_unless($school, 404);

        $module = DB::table('modules')->where('id', $moduleId)->where('is_sellable', true)->first();
        abort_unless($module, 404);

        $existing = DB::table('school_modules')
            ->where('school_id', $id)
            ->where('module_id', $moduleId)
            ->first();

        if ($existing) {
            $newEnabled = ! $existing->enabled;
            DB::table('school_modules')
                ->where('school_id', $id)
                ->where('module_id', $moduleId)
                ->update([
                    'enabled' => $newEnabled,
                    $newEnabled ? 'enabled_by' : 'disabled_by' => $request->user()?->id,
                    'updated_at' => now(),
                ]);
        } else {
            DB::table('school_modules')->insert([
                'school_id' => $id,
                'module_id' => $moduleId,
                'enabled' => true,
                'starts_at' => now(),
                'enabled_by' => $request->user()?->id,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }

        return redirect()->route('super-admin.schools.modules', $id)->with('success', 'وضعیت ماژول تغییر کرد.');
    }

    public function exportZip(int $id): \Symfony\Component\HttpFoundation\Response
    {
        $school = DB::table('schools')->where('id', $id)->first(['name_fa', 'school_code']);
        abort_unless($school, 404);

        $slug = preg_replace('/[^a-zA-Z0-9_\-]/', '', $school->school_code ?? 'school') ?: 'school';
        $tmpDir = sys_get_temp_dir().'/daneshyar_sa_export_'.$id.'_'.time();
        mkdir($tmpDir, 0700, true);

        try {
            $csvSets = [
                ['students.csv', ['student_code', 'first_name', 'last_name', 'mobile', 'grade', 'status'],
                    DB::table('students')
                        ->leftJoin('grade_levels', 'grade_levels.id', '=', 'students.grade_level_id')
                        ->where('students.school_id', $id)
                        ->get(['students.student_code', 'students.first_name', 'students.last_name', 'students.mobile', 'grade_levels.name_fa as grade', 'students.status'])],
                ['teachers.csv', ['teacher_code', 'first_name', 'last_name', 'mobile', 'specialty', 'status'],
                    DB::table('teachers')->where('school_id', $id)->get(['teacher_code', 'first_name', 'last_name', 'mobile', 'specialty', 'status'])],
                ['users.csv', ['username', 'first_name', 'last_name', 'mobile', 'role_key', 'status'],
                    DB::table('users')->where('school_id', $id)->get(['username', 'first_name', 'last_name', 'mobile', 'role_key', 'status'])],
                ['grades.csv', ['student_code', 'first_name', 'last_name', 'subject', 'classroom', 'score', 'max_score', 'status'],
                    DB::table('grades')
                        ->join('students', 'students.id', '=', 'grades.student_id')
                        ->leftJoin('subjects', 'subjects.id', '=', 'grades.subject_id')
                        ->leftJoin('classrooms', 'classrooms.id', '=', 'grades.classroom_id')
                        ->where('grades.school_id', $id)
                        ->get(['students.student_code', 'students.first_name', 'students.last_name', 'subjects.name_fa as subject', 'classrooms.name as classroom', 'grades.score', 'grades.max_score', 'grades.status'])],
            ];

            foreach ($csvSets as [$filename, $headers, $rows]) {
                $handle = fopen($tmpDir.'/'.$filename, 'w');
                fwrite($handle, "\xEF\xBB\xBF");
                fputcsv($handle, $headers);
                foreach ($rows as $row) {
                    fputcsv($handle, array_map(fn ($h) => $row->{$h} ?? '', $headers));
                }
                fclose($handle);
            }

            $zipFile = sys_get_temp_dir().'/daneshyar_export_'.$slug.'_'.date('Ymd').'.zip';
            $zip = new \ZipArchive();
            if ($zip->open($zipFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
                abort(500);
            }
            foreach (glob($tmpDir.'/*.csv') as $f) {
                $zip->addFile($f, basename($f));
            }
            $zip->close();

            return response()->download($zipFile, 'school_'.$slug.'_'.date('Ymd').'.zip', [
                'Content-Type' => 'application/zip',
            ])->deleteFileAfterSend(true);
        } finally {
            foreach (glob($tmpDir.'/*.csv') ?: [] as $f) {
                @unlink($f);
            }
            @rmdir($tmpDir);
        }
    }
}
