<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\HomepageSection;
use App\Models\Media;
use App\Services\AppearanceService;
use App\Services\SectionService;
use App\Support\AppearanceRegistry;
use Illuminate\Http\Request;
use Laracasts\Flash\Flash;

class AppearanceController extends Controller
{
    protected array $data = [];

    public function __construct()
    {
        $this->data['title'] = 'Appearance';
    }

    public function index()
    {
        return redirect()->route('ch-admin.appearance.branding');
    }

    public function branding()
    {
        $this->data['tab'] = 'branding';

        $this->data['logo'] = json_encode(
            Media::where('id', setting('app.logo'))->get()->map(fn($m) => [
                'id'        => $m->id,
                'name'      => $m->filename . '.' . $m->extension,
                'image_url' => $m->getUrl('thumbnail'),
                'size'      => $m->size,
            ])
        );

        $this->data['favicon'] = json_encode(
            Media::where('id', setting('app.favicon'))->get()->map(fn($m) => [
                'id'        => $m->id,
                'name'      => $m->filename . '.' . $m->extension,
                'image_url' => $m->getUrl('thumbnail'),
                'size'      => $m->size,
            ])
        );

        $this->data['logo_max_width'] = appearance('branding.logo_max_width');
        $this->data['logo_alt']       = appearance('branding.logo_alt');

        return view('admin.appearance.index', $this->data);
    }

    public function updateBranding(Request $request)
    {
        $request->validate([
            'logo_max_width' => 'nullable|integer|min:0|max:500',
            'logo_alt'       => 'nullable|string|max:200',
        ]);

        // Primary logo and favicon save back to the settings table (unchanged behaviour)
        if ($request->has('settings')) {
            foreach ($request->input('settings', []) as $group => $keys) {
                foreach ($keys as $key => $value) {
                    \App\Models\Setting::updateOrCreate(
                        ['key' => "{$group}.{$key}"],
                        ['value' => $value]
                    );
                }
            }
            \Illuminate\Support\Facades\Cache::forget('settings');
        }

        // Branding appearance settings
        $maxWidth = $request->input('logo_max_width');
        app(AppearanceService::class)->setMany([
            'branding.logo_max_width' => $maxWidth ? (int) $maxWidth : null,
            'branding.logo_alt'       => $request->input('logo_alt') ?: null,
        ]);

        Flash::success('Branding settings saved.');

        return redirect()->route('ch-admin.appearance.branding');
    }

    public function colors()
    {
        $this->data['tab'] = 'colors';

        $colors = [];
        foreach (AppearanceRegistry::group('colors') as $fullKey => $def) {
            $shortKey = str_replace('colors.', '', $fullKey);
            $colors[$shortKey] = [
                'label'   => $def['label'],
                'default' => $def['default'],
                'value'   => appearance($fullKey, $def['default']),
            ];
        }
        $this->data['colors'] = $colors;

        return view('admin.appearance.index', $this->data);
    }

    public function updateColors(Request $request)
    {
        $request->validate([
            'colors'   => 'array',
            'colors.*' => ['nullable', 'regex:/^#[0-9a-fA-F]{6}$/'],
        ]);

        $definitions = AppearanceRegistry::definitions();
        $values      = [];
        foreach ($request->input('colors', []) as $shortKey => $value) {
            $fullKey = 'colors.' . $shortKey;
            if (isset($definitions[$fullKey])) {
                $values[$fullKey] = $value ?: null;
            }
        }

        app(AppearanceService::class)->setMany($values);

        Flash::success('Color settings saved.');

        return redirect()->route('ch-admin.appearance.colors');
    }

    public function typography()
    {
        $this->data['tab'] = 'typography';

        $typography = [];
        foreach (AppearanceRegistry::group('typography') as $fullKey => $def) {
            $shortKey = str_replace('typography.', '', $fullKey);
            $typography[$shortKey] = [
                'label'   => $def['label'],
                'default' => $def['default'],
                'options' => $def['options'],
                'value'   => appearance($fullKey, $def['default']),
            ];
        }
        $this->data['typography'] = $typography;

        return view('admin.appearance.index', $this->data);
    }

    public function updateTypography(Request $request)
    {
        $fontOptions   = AppearanceRegistry::definitions()['typography.font_family']['options'];
        $sizeOptions   = AppearanceRegistry::definitions()['typography.base_font_size']['options'];
        $weightOptions = AppearanceRegistry::definitions()['typography.heading_weight']['options'];

        $request->validate([
            'font_family'    => ['nullable', 'string', 'in:' . implode(',', $fontOptions)],
            'base_font_size' => ['nullable', 'string', 'in:' . implode(',', $sizeOptions)],
            'heading_weight' => ['nullable', 'string', 'in:' . implode(',', $weightOptions)],
        ]);

        app(AppearanceService::class)->setMany([
            'typography.font_family'    => $request->input('font_family') ?: null,
            'typography.base_font_size' => $request->input('base_font_size') ?: null,
            'typography.heading_weight' => $request->input('heading_weight') ?: null,
        ]);

        Flash::success('Typography settings saved.');

        return redirect()->route('ch-admin.appearance.typography');
    }

    public function homepage()
    {
        $this->data['tab']      = 'homepage';
        $this->data['sections'] = app(SectionService::class)->allOrdered();

        return view('admin.appearance.index', $this->data);
    }

    public function updateHomepage(Request $request)
    {
        $request->validate([
            'sections'                    => 'required|array',
            'sections.*.slug'             => 'required|string',
            'sections.*.is_visible'       => 'nullable|boolean',
            'sections.*.sort_order'       => 'nullable|integer',
            'sections.*.config.count'     => 'nullable|integer|min:1|max:24',
        ]);

        $sectionService = app(SectionService::class);
        $order          = [];

        foreach ($request->input('sections') as $item) {
            $slug = $item['slug'];
            $order[] = $slug;

            $sectionService->setVisible($slug, isset($item['is_visible']));

            if (isset($item['config'])) {
                $sectionService->updateConfig($slug, $item['config']);
            }
        }

        $sectionService->reorder($order);

        Flash::success('Homepage settings saved.');

        return redirect()->route('ch-admin.appearance.homepage');
    }

    public function advanced()
    {
        $this->data['tab']            = 'advanced';
        $this->data['custom_css']     = appearance('advanced.custom_css', '');
        $this->data['import_preview'] = session('import_preview');

        return view('admin.appearance.index', $this->data);
    }

    public function updateAdvanced(Request $request)
    {
        $request->validate([
            'custom_css' => 'nullable|string|max:65535',
        ]);

        app(AppearanceService::class)->setMany([
            'advanced.custom_css' => $request->input('custom_css') ?: null,
        ]);

        Flash::success('Custom CSS saved.');

        return redirect()->route('ch-admin.appearance.advanced');
    }

    public function export()
    {
        $service        = app(AppearanceService::class);
        $sectionService = app(SectionService::class);
        $definitions    = AppearanceRegistry::definitions();

        $settings = [];
        foreach ($definitions as $key => $def) {
            $value = $service->get($key);
            if ($value !== null) {
                $settings[$key] = $value;
            }
        }

        $payload = [
            'version'             => 1,
            'exported_at'         => now()->toIso8601String(),
            'appearance_settings' => $settings,
            'homepage_sections'   => $sectionService->allOrdered()->map(fn($s) => [
                'slug'       => $s->slug,
                'is_visible' => $s->is_visible,
                'sort_order' => $s->sort_order,
                'config'     => $s->config,
            ])->values()->toArray(),
        ];

        return response()->json($payload, 200, [
            'Content-Disposition' => 'attachment; filename="appearance-export.json"',
        ], JSON_PRETTY_PRINT);
    }

    public function import(Request $request)
    {
        $request->validate([
            'import_file' => 'required|file|mimes:json,txt|max:512',
        ]);

        $json = file_get_contents($request->file('import_file')->getRealPath());
        $data = json_decode($json, true);

        if (json_last_error() !== JSON_ERROR_NONE || ! is_array($data)) {
            Flash::error('Invalid JSON file.');
            return redirect()->route('ch-admin.appearance.advanced');
        }

        $definitions    = AppearanceRegistry::definitions();
        $service        = app(AppearanceService::class);
        $sectionService = app(SectionService::class);
        $changes        = [];

        foreach ($data['appearance_settings'] ?? [] as $key => $value) {
            if (! isset($definitions[$key])) {
                continue;
            }
            $current = $service->get($key);
            if ((string) $current !== (string) $value) {
                $changes[] = [
                    'type'    => 'setting',
                    'key'     => $key,
                    'label'   => $definitions[$key]['label'],
                    'current' => $current,
                    'new'     => $value,
                ];
            }
        }

        $allSections = $sectionService->allOrdered()->keyBy('slug');
        foreach ($data['homepage_sections'] ?? [] as $s) {
            $slug = $s['slug'] ?? null;
            if (! $slug || ! $allSections->has($slug)) {
                continue;
            }
            $existing   = $allSections[$slug];
            $newVisible = (bool) ($s['is_visible'] ?? true);
            $newOrder   = (int) ($s['sort_order'] ?? 0);
            if ((bool) $existing->is_visible !== $newVisible || (int) $existing->sort_order !== $newOrder) {
                $changes[] = [
                    'type'    => 'section',
                    'key'     => $slug,
                    'label'   => "Section: {$slug}",
                    'current' => 'visible=' . ($existing->is_visible ? 'yes' : 'no') . ', order=' . $existing->sort_order,
                    'new'     => 'visible=' . ($newVisible ? 'yes' : 'no') . ', order=' . $newOrder,
                ];
            }
        }

        if (empty($changes)) {
            Flash::success('No changes detected — settings already match the import file.');
            return redirect()->route('ch-admin.appearance.advanced');
        }

        session(['import_preview' => [
            'changes' => $changes,
            'payload' => $data,
        ]]);

        return redirect()->route('ch-admin.appearance.advanced');
    }

    public function importApply()
    {
        $preview = session('import_preview');

        if (! $preview) {
            Flash::error('No import pending.');
            return redirect()->route('ch-admin.appearance.advanced');
        }

        $data           = $preview['payload'];
        $definitions    = AppearanceRegistry::definitions();
        $service        = app(AppearanceService::class);
        $sectionService = app(SectionService::class);

        $values = [];
        foreach ($data['appearance_settings'] ?? [] as $key => $value) {
            if (isset($definitions[$key])) {
                $values[$key] = $value;
            }
        }
        if ($values) {
            $service->setMany($values);
        }

        $allSections = $sectionService->allOrdered()->keyBy('slug');
        $order       = [];
        foreach ($data['homepage_sections'] ?? [] as $s) {
            $slug = $s['slug'] ?? null;
            if (! $slug || ! $allSections->has($slug)) {
                continue;
            }
            $order[] = $slug;
            $sectionService->setVisible($slug, (bool) ($s['is_visible'] ?? true));
            if (isset($s['config'])) {
                $sectionService->updateConfig($slug, $s['config']);
            }
        }
        if ($order) {
            $sectionService->reorder($order);
        }

        session()->forget('import_preview');

        Flash::success('Appearance settings imported successfully.');

        return redirect()->route('ch-admin.appearance.advanced');
    }

    public function importCancel()
    {
        session()->forget('import_preview');

        return redirect()->route('ch-admin.appearance.advanced');
    }
}
