<?php

namespace App\Http\Controllers;

use App\Models\AttendanceSetting;
use App\Models\CompanySetting;
use App\Models\ConsultationSetting;
use App\Models\DeletedRecord;
use App\Models\PosCardSetting;
use App\Models\WebsiteApplication;
use App\Models\WebsiteHeroSetting;
use App\Models\WebsiteProgram;
use App\Models\WebsiteWebsite;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;

class SettingsController extends Controller
{
    public function __construct()
    {
        $this->middleware('permission:settings.company_info.view')->only(['companyInfo']);
        $this->middleware('permission:settings.company_info.update')->only(['storeCompanyInfo']);

        $this->middleware('permission:settings.pos_settings.view')->only(['posSettings']);
        $this->middleware('permission:settings.pos_settings.update')->only(['storePosSettings']);

        $this->middleware('permission:settings.attendance_settings.view')->only(['attendanceSettings']);
        $this->middleware('permission:settings.attendance_settings.update')->only(['storeAttendanceSettings']);

        $this->middleware('permission:settings.view')->only(['consultationsSettings']);
        $this->middleware('permission:settings.view')->only(['storeConsultationsSettings']);

        $this->middleware('permission:settings.deleted_records.view')->only(['deletedRecords']);
        $this->middleware('permission:settings.deleted_records.update')->only(['restoreDeletedRecord']);
        $this->middleware('permission:settings.deleted_records.delete')->only(['forceDeleteDeletedRecord']);
    }

    public function companyInfo()
    {
        $company = Schema::hasTable('company_settings')
            ? CompanySetting::query()->first()
            : null;

        return view('settings.company_info', compact('company'));
    }

    public function storeCompanyInfo(Request $request)
    {
        if (! Schema::hasTable('company_settings')) {
            return redirect()->route('settings.company-info');
        }

        $data = $request->validate([
            'name_ar' => ['nullable', 'string', 'max:255'],
            'name_en' => ['nullable', 'string', 'max:255'],
            'address_ar' => ['nullable', 'string', 'max:255'],
            'address_en' => ['nullable', 'string', 'max:255'],
            'phone_1' => ['nullable', 'string', 'max:50'],
            'phone_2' => ['nullable', 'string', 'max:50'],
            'email' => ['nullable', 'email', 'max:255'],
            'logo' => ['nullable', 'image'],
        ]);

        $company = CompanySetting::query()->firstOrCreate(['id' => 1]);

        if ($request->hasFile('logo')) {
            $data['logo'] = $request->file('logo')->store('company', 'public');
        } else {
            $data['logo'] = $company->logo;
        }

        $company->fill($data)->save();

        return redirect()->route('settings.company-info')->with('success', __('common.saved_successfully'));
    }

    public function posSettings()
    {
        if (! Schema::hasTable('pos_card_settings')) {
            $cards = collect();

            return view('settings.pos_settings', compact('cards'));
        }

        $defaults = [
            [
                'key' => 'services',
                'name_ar' => Lang::get('pos.cards.services', [], 'ar'),
                'name_en' => Lang::get('pos.cards.services', [], 'en'),
                'is_visible' => true,
            ],
            [
                'key' => 'products',
                'name_ar' => Lang::get('pos.cards.products', [], 'ar'),
                'name_en' => Lang::get('pos.cards.products', [], 'en'),
                'is_visible' => true,
            ],
            [
                'key' => 'stage_academy',
                'name_ar' => Lang::get('pos.cards.stage_academy', [], 'ar'),
                'name_en' => Lang::get('pos.cards.stage_academy', [], 'en'),
                'is_visible' => true,
            ],
        ];

        foreach ($defaults as $row) {
            PosCardSetting::query()->firstOrCreate(
                ['key' => $row['key']],
                ['name_ar' => $row['name_ar'], 'name_en' => $row['name_en'], 'is_visible' => $row['is_visible']]
            );
        }

        $cards = PosCardSetting::query()->orderBy('id')->get();

        return view('settings.pos_settings', compact('cards'));
    }

    public function storePosSettings(Request $request)
    {
        if (! Schema::hasTable('pos_card_settings')) {
            return redirect()->route('settings.pos-settings');
        }

        $data = $request->validate([
            'cards' => ['nullable', 'array'],
            'cards.*.is_visible' => ['nullable', 'boolean'],
        ]);

        $cards = PosCardSetting::query()->get();
        foreach ($cards as $card) {
            $isVisible = (bool) data_get($data, "cards.{$card->id}.is_visible", false);
            $card->update(['is_visible' => $isVisible]);
        }

        return redirect()->route('settings.pos-settings')->with('success', __('common.saved_successfully'));
    }

    public function attendanceSettings()
    {
        $settings = Schema::hasTable('attendance_settings')
            ? AttendanceSetting::query()->firstOrCreate(['id' => 1], ['allowed_radius' => 50])
            : null;

        return view('settings.attendance_settings', [
            'settings' => $settings,
        ]);
    }

    public function storeAttendanceSettings(Request $request)
    {
        if (! Schema::hasTable('attendance_settings')) {
            return redirect()->route('settings.attendance-settings');
        }

        $latitude = $this->normalizeCoordinate($request->input('latitude'));
        $longitude = $this->normalizeCoordinate($request->input('longitude'));
        $request->merge([
            'latitude' => $latitude ?? $request->input('latitude'),
            'longitude' => $longitude ?? $request->input('longitude'),
        ]);

        $data = $request->validate([
            'longitude' => ['required', 'numeric'],
            'latitude' => ['required', 'numeric'],
            'allowed_radius' => ['required', 'integer', 'min:1'],
            'late_minute_price' => ['nullable', 'integer', 'min:0'],
            'absence_deduction_days' => ['nullable', 'integer', 'in:1,2,3'],
            'unpaid_leave_deduction_days' => ['nullable', 'integer', 'in:1,2,3'],
            'missing_checkout_penalty_amount' => ['nullable', 'integer', 'min:0'],
        ]);

        $settings = AttendanceSetting::query()->firstOrCreate(['id' => 1], ['allowed_radius' => 50]);
        $settings->fill($data)->save();

        return redirect()->route('settings.attendance-settings')->with('success', __('common.saved_successfully'));
    }

    public function consultationsSettings()
    {
        $settings = Schema::hasTable('consultation_settings')
            ? ConsultationSetting::query()->firstOrCreate(['id' => 1], ['campaign_management_enabled' => true])
            : null;

        return view('settings.consultations_settings', [
            'settings' => $settings,
        ]);
    }

    public function storeConsultationsSettings(Request $request)
    {
        if (! Schema::hasTable('consultation_settings')) {
            return redirect()->route('settings.consultations-settings');
        }

        $data = $request->validate([
            'campaign_management_enabled' => ['nullable', 'boolean'],
        ]);

        $settings = ConsultationSetting::query()->firstOrCreate(['id' => 1], ['campaign_management_enabled' => true]);
        $settings->fill([
            'campaign_management_enabled' => (bool) ($data['campaign_management_enabled'] ?? false),
        ])->save();

        return redirect()->route('settings.consultations-settings')->with('success', __('common.saved_successfully'));
    }

    private function normalizeCoordinate(mixed $value): ?string
    {
        if (! is_string($value) && ! is_numeric($value)) {
            return null;
        }

        $raw = trim((string) $value);
        if ($raw === '') {
            return null;
        }

        $raw = str_replace(['٫', ','], '.', $raw);

        if (preg_match('/^-?\d+(?:\.\d+)?$/', $raw) === 1) {
            return $raw;
        }

        $normalized = preg_replace('/[^\d\.\-\+]+/u', ' ', $raw);
        $parts = array_values(array_filter(preg_split('/\s+/', (string) $normalized), fn ($p) => $p !== ''));
        $parts = array_slice($parts, 0, 3);

        if (count($parts) < 2) {
            return null;
        }

        $deg = (float) $parts[0];
        $min = (float) ($parts[1] ?? 0);
        $sec = (float) ($parts[2] ?? 0);

        $sign = $deg < 0 ? -1 : 1;
        $deg = abs($deg);

        $decimal = ($deg + ($min / 60) + ($sec / 3600)) * $sign;

        return number_format($decimal, 7, '.', '');
    }

    public function deletedRecords(Request $request)
    {
        if (! Schema::hasTable('deleted_records')) {
            $records = new LengthAwarePaginator([], 0, 20, 1, [
                'path' => $request->url(),
                'query' => $request->query(),
            ]);

            return view('settings.deleted_records', compact('records'));
        }

        $type = trim((string) $request->query('type', ''));

        $records = DeletedRecord::query()
            ->with(['deletedBy'])
            ->when($type !== '', fn ($q) => $q->where('type', $type))
            ->orderByDesc('deleted_at')
            ->paginate(20)
            ->appends($request->all());

        $typeOptions = collect(DeletedRecord::typeMap())->keys()->values();

        return view('settings.deleted_records', compact('records', 'type', 'typeOptions'));
    }

    public function websiteSettings(?string $section = null)
    {
        if ($section === 'header') {
            return redirect()->route('settings.website.hero');
        }
        if ($section === 'apps') {
            return redirect()->route('settings.website.apps');
        }
        if ($section === 'websites') {
            return redirect()->route('settings.website.websites');
        }
        if ($section === 'programs') {
            return redirect()->route('settings.website.programs');
        }

        $sections = [
            'header' => __('settings.website.sections.header'),
            'footer' => __('settings.website.sections.footer'),
            'programs' => __('settings.website.sections.programs'),
        ];

        $sectionKey = $section && array_key_exists($section, $sections) ? $section : null;
        $activeTitle = $sectionKey ? $sections[$sectionKey] : __('settings.website.title');

        return view('settings.website_settings', [
            'sectionKey' => $sectionKey,
            'activeTitle' => $activeTitle,
        ]);
    }

    public function websiteHeroSettings()
    {
        $settings = Schema::hasTable('website_hero_settings')
            ? WebsiteHeroSetting::query()->firstOrCreate(['id' => 1], ['show_image' => true])
            : null;

        return view('settings.website_hero_settings', [
            'settings' => $settings,
        ]);
    }

    public function storeWebsiteHeroSettings(Request $request)
    {
        if (! Schema::hasTable('website_hero_settings')) {
            return redirect()->route('settings.website.hero');
        }

        $data = $request->validate([
            'show_image' => ['nullable', 'boolean'],
            'remove_image' => ['nullable', 'boolean'],
            'image' => ['nullable', 'image', 'max:6144'],
        ]);

        $settings = WebsiteHeroSetting::query()->firstOrCreate(['id' => 1], ['show_image' => true]);

        $removeImage = (bool) ($data['remove_image'] ?? false);
        $showImage = (bool) ($data['show_image'] ?? false);

        if ($removeImage && $settings->image) {
            Storage::disk('public')->delete($settings->image);
            $settings->image = null;
        }

        if ($request->hasFile('image')) {
            if ($settings->image) {
                Storage::disk('public')->delete($settings->image);
            }
            $settings->image = $request->file('image')->store('website/hero', 'public');
        }

        $settings->show_image = $showImage;
        $settings->save();

        return redirect()->route('settings.website.hero')->with('success', __('common.saved_successfully'));
    }

    public function websiteAppsSettings()
    {
        $apps = Schema::hasTable('website_applications')
            ? WebsiteApplication::query()->latest()->get()
            : collect();

        return view('settings.website_apps_settings', [
            'apps' => $apps,
        ]);
    }

    public function storeWebsiteApp(Request $request)
    {
        if (! Schema::hasTable('website_applications')) {
            return redirect()->route('settings.website.apps');
        }

        $data = $request->validate([
            'name_ar' => ['required', 'string', 'max:255'],
            'name_en' => ['required', 'string', 'max:255'],
            'name_ku' => ['required', 'string', 'max:255'],
            'details_ar' => ['required', 'string'],
            'details_en' => ['required', 'string'],
            'details_ku' => ['required', 'string'],
            'apple_url' => ['required', 'url', 'max:2048'],
            'android_url' => ['required', 'url', 'max:2048'],
            'logo' => ['required', 'image', 'max:4096'],
        ]);

        $logoPath = $request->file('logo')->store('website/apps', 'public');
        $data['logo_ar'] = $logoPath;
        $data['logo_en'] = $logoPath;
        $data['logo_ku'] = $logoPath;
        $data['apple_url_ar'] = $data['apple_url'];
        $data['apple_url_en'] = $data['apple_url'];
        $data['apple_url_ku'] = $data['apple_url'];
        $data['android_url_ar'] = $data['android_url'];
        $data['android_url_en'] = $data['android_url'];
        $data['android_url_ku'] = $data['android_url'];
        unset($data['apple_url'], $data['android_url'], $data['logo']);

        WebsiteApplication::query()->create($data);

        return redirect()->route('settings.website.apps')->with('success', __('common.saved_successfully'));
    }

    public function publicAppsPage(string $locale = 'en')
    {
        $locale = in_array($locale, ['en', 'ar', 'ku'], true) ? $locale : 'en';
        $apps = Schema::hasTable('website_applications')
            ? WebsiteApplication::query()->latest()->get()
            : collect();

        return view('public.works_apps', [
            'locale' => $locale,
            'apps' => $apps,
            'heroSettings' => Schema::hasTable('website_hero_settings')
                ? WebsiteHeroSetting::query()->first()
                : null,
        ]);
    }

    public function publicHomePage(string $locale = 'en')
    {
        $locale = in_array($locale, ['en', 'ar', 'ku'], true) ? $locale : 'en';

        return view('public.home', [
            'locale' => $locale,
            'heroSettings' => Schema::hasTable('website_hero_settings')
                ? WebsiteHeroSetting::query()->first()
                : null,
        ]);
    }

    public function websiteWebsitesSettings()
    {
        $websites = Schema::hasTable('website_websites')
            ? WebsiteWebsite::query()->latest()->get()
            : collect();

        return view('settings.website_websites_settings', [
            'websites' => $websites,
        ]);
    }

    public function storeWebsiteWebsite(Request $request)
    {
        if (! Schema::hasTable('website_websites')) {
            return redirect()->route('settings.website.websites');
        }

        $data = $request->validate([
            'name_ar' => ['required', 'string', 'max:255'],
            'name_en' => ['required', 'string', 'max:255'],
            'name_ku' => ['required', 'string', 'max:255'],
            'details_ar' => ['required', 'string'],
            'details_en' => ['required', 'string'],
            'details_ku' => ['required', 'string'],
            'url' => ['required', 'url', 'max:2048'],
            'logo' => ['required', 'image', 'max:4096'],
        ]);

        $data['logo'] = $request->file('logo')->store('website/websites', 'public');

        WebsiteWebsite::query()->create($data);

        return redirect()->route('settings.website.websites')->with('success', __('common.saved_successfully'));
    }

    public function publicWebsitesPage(string $locale = 'en')
    {
        $locale = in_array($locale, ['en', 'ar', 'ku'], true) ? $locale : 'en';
        $websites = Schema::hasTable('website_websites')
            ? WebsiteWebsite::query()->latest()->get()
            : collect();

        return view('public.works_websites', [
            'locale' => $locale,
            'websites' => $websites,
            'heroSettings' => Schema::hasTable('website_hero_settings')
                ? WebsiteHeroSetting::query()->first()
                : null,
        ]);
    }

    public function websiteProgramsSettings()
    {
        $programs = Schema::hasTable('website_programs')
            ? WebsiteProgram::query()->latest()->get()
            : collect();

        return view('settings.website_programs_settings', [
            'programs' => $programs,
        ]);
    }

    public function storeWebsiteProgram(Request $request)
    {
        if (! Schema::hasTable('website_programs')) {
            return redirect()->route('settings.website.programs');
        }

        $data = $request->validate([
            'name_ar' => ['required', 'string', 'max:255'],
            'name_en' => ['required', 'string', 'max:255'],
            'name_ku' => ['required', 'string', 'max:255'],
            'details_ar' => ['required', 'string'],
            'details_en' => ['required', 'string'],
            'details_ku' => ['required', 'string'],
            'url' => ['required', 'url', 'max:2048'],
            'logo' => ['required', 'image', 'max:4096'],
        ]);

        $data['logo'] = $request->file('logo')->store('website/programs', 'public');

        WebsiteProgram::query()->create($data);

        return redirect()->route('settings.website.programs')->with('success', __('common.saved_successfully'));
    }

    public function publicProgramsPage(string $locale = 'en')
    {
        $locale = in_array($locale, ['en', 'ar', 'ku'], true) ? $locale : 'en';
        $programs = Schema::hasTable('website_programs')
            ? WebsiteProgram::query()->latest()->get()
            : collect();

        return view('public.works_programs', [
            'locale' => $locale,
            'programs' => $programs,
            'heroSettings' => Schema::hasTable('website_hero_settings')
                ? WebsiteHeroSetting::query()->first()
                : null,
        ]);
    }

    public function restoreDeletedRecord(string $type, int $id)
    {
        if (! Schema::hasTable('deleted_records')) {
            return redirect()->route('settings.deleted-records');
        }

        $class = DeletedRecord::typeMap()[$type] ?? null;
        if (! $class) {
            return redirect()->route('settings.deleted-records');
        }

        $model = $class::withTrashed()->findOrFail($id);
        $model->restore();

        DeletedRecord::query()
            ->where('type', $type)
            ->where('record_id', $id)
            ->whereNull('force_deleted_at')
            ->update([
                'restored_at' => now(),
                'restored_by' => Auth::id(),
            ]);

        return redirect()->route('settings.deleted-records')->with('success', __('common.saved_successfully'));
    }

    public function forceDeleteDeletedRecord(string $type, int $id)
    {
        if (! Schema::hasTable('deleted_records')) {
            return redirect()->route('settings.deleted-records');
        }

        $class = DeletedRecord::typeMap()[$type] ?? null;
        if (! $class) {
            return redirect()->route('settings.deleted-records');
        }

        $model = $class::withTrashed()->findOrFail($id);
        $model->forceDelete();

        DeletedRecord::query()
            ->where('type', $type)
            ->where('record_id', $id)
            ->whereNull('force_deleted_at')
            ->update([
                'force_deleted_at' => now(),
                'force_deleted_by' => Auth::id(),
            ]);

        return redirect()->route('settings.deleted-records')->with('success', __('common.deleted_successfully'));
    }
}
