<?php

namespace App\Http\Controllers;

use App\Models\CalendarInstance;
use App\Models\CalendarMeta;
use App\Models\Subscription;
use App\Services\Calendar\CreateCalendar;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;

class CalendarSettingsController extends Controller
{
    /* landing page shows the first settings pane */
    public function index()
    {
        return redirect()->route('calendar.settings.display');
    }

    /**
     * Create a local calendar
     **/

    public function createForm(Request $request)
    {
        $user = $request->user();

        $data = [
            'title' => __('calendar.settings.create.title'),
            'sub'   => __('calendar.settings.create.subtitle'),
            'defaults' => [
                'name'        => '',
                'description' => '',
                'timezone'    => $user->timezone ?? config('app.timezone', 'UTC'),
                'color'       => default_calendar_color(),
            ],
            'redirect' => route('calendar.settings'),
        ];

        if ($request->header('HX-Request')) {
            $data['redirect'] = route('calendar.index');
            return view('calendar.partials.create-modal', $data);
        }

        return $this->frame('calendar.settings.create', $data);
    }

    public function createStore(Request $request, CreateCalendar $creator)
    {
        $data = $request->validate([
            'name'        => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
            'timezone'    => 'required|string',
            'color'       => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
        ]);

        $creator->create($request->user(), $data);
        $redirect = $data['redirect'] ?? route('calendar.index');

        return redirect($redirect)->with('toast', [
            'message' => __('Calendar created!'),
            'type'    => 'success',
        ]);
    }

    /**
     *
     * Display preferences
     */
    public function displayForm(Request $request)
    {
        $user = $request->user();

        $data = [
            'title' => __('calendar.settings.display.title'),
            'sub'   => __('calendar.settings.display.subtitle'),
            'defaults' => [
                // store as: 'sunday' | 'monday'
                'week_start' => $user->getSetting('calendar.week_start', 'monday'),
            ],
        ];

        return $this->frame('calendar.settings.display', $data);
    }

    public function displayStore(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'week_start' => ['required', 'in:sunday,monday'],
        ]);

        $user = $request->user();
        $user->setSetting('calendar.week_start', $data['week_start']);

        return Redirect::route('calendar.settings.display')
            ->with('toast', [
                'message' => __('calendar.settings.saved'),
                'type'    => 'success',
            ]);
    }

    /**
     *
     * Subscribe
     */
    public function subscribeForm()
    {
        return $this->frame(
            'calendar.settings.subscribe',
            [
                'title' => __('calendar.settings.subscribe.title'),
                'sub'   => __('calendar.settings.subscribe.subtitle'),
            ]);
    }

    public function subscribeStore(Request $request)
    {
        $data = $request->validate([
            'source' => ['required', 'url'],
            'displayname' => ['nullable', 'string', 'max:100'],
            'color' => ['nullable', 'regex:/^#[0-9A-F]{6}$/i'],
        ]);

        // create the calendarsubscription and calendar_meta rows in one call via Subscription model
        Subscription::createWithMeta(
            $request->user(),
            [
                'source'        => $data['source'],
                'displayname'   => $data['displayname'] ?: $data['source'],
                'calendarcolor' => calendar_color($data),
                // you can add 'refreshrate' => 'P1D' here if you like
            ]
        );

        return redirect()
            ->route('calendar.index')
            ->with('toast', __('Subscription added successfully!'));
    }


    /**
     *
     * Individual calendar settings
     */
    public function calendarForm(Request $request, string $calendarUri)
    {
        $user = $request->user();
        $principalUri = $user->uri;

        // this is the user's "instance" of the calendar (displayname/color/etc live here in sabre)
        $instance = CalendarInstance::query()
            ->where('principaluri', $principalUri)
            ->where('uri', $calendarUri)
            ->firstOrFail();

        // your app meta (optional row)
        $meta = $instance->meta;

        // if it's remote
        $icsUrl = null;
        $shareUrl = null;
        $isRemote = (bool) ($meta?->is_remote ?? false);
        $isShared = (bool) ($meta?->is_shared ?? false);

        if ($isRemote && $meta?->subscription_id) {
            $icsUrl = Subscription::query()
                ->whereKey($meta->subscription_id)
                ->value('source');
        }

        if (!$isRemote && $isShared) {
            $shareUrl = route('calendar.ics', ['calendarUri' => $instance->uri]);
        }

        return $this->frame(
            'calendar.settings.calendar',
            [
                'title'    => __('calendar.settings.calendar.title'),
                'sub'      => __('calendar.settings.calendar.subtitle'),
                'instance' => $instance,
                'meta'     => $meta,
                'icsUrl'   => $icsUrl,
                'shareUrl' => $shareUrl,
                'userTz'   => $user->timezone,
            ]);
    }

    public function calendarStore(Request $request, string $calendarUri): RedirectResponse
    {
        $user = $request->user();
        $principalUri = $user->uri;

        $instance = CalendarInstance::query()
            ->where('principaluri', $principalUri)
            ->where('uri', $calendarUri)
            ->with('meta')
            ->firstOrFail();

        $data = $request->validate([
            'displayname'   => ['required', 'string', 'max:100'],
            'description'   => ['nullable', 'string', 'max:500'],
            'timezone'      => ['nullable', 'string', 'max:64'],
            'color'         => ['nullable', 'regex:/^#[0-9A-F]{6}$/i'],
            'is_shared'     => ['nullable', 'boolean'],
        ]);

        $timezone = filled($data['timezone'] ?? null)
            ? $data['timezone']
            : $user->timezone;

        $color = $data['color'] ?? $instance->resolvedColor();

        DB::transaction(function () use ($instance, $data, $timezone, $color) {
            $isRemote = (bool) ($instance->meta?->is_remote ?? false);
            $isShared = $isRemote ? false : (bool) ($data['is_shared'] ?? false);

            // update sabre calendar instance (dav-facing)
            $instance->update([
                'displayname'   => $data['displayname'],
                'description'   => $data['description'] ?? null,
                'timezone'      => $timezone,
                'calendarcolor' => $color,
            ]);

            // update ui meta (kithkin-facing)
            CalendarMeta::updateOrCreate(
                ['calendar_id' => $instance->calendarid],
                [
                    'title'    => $data['displayname'],
                    'color'    => $color,
                    'color_fg' => contrast_text_color($color),
                    'is_shared' => $isShared,
                ]
            );
        });

        return Redirect::route('calendar.settings.calendars.show', $calendarUri)
            ->with('toast', [
                'message' => __('calendar.settings.saved'),
                'type'    => 'success',
            ]);
    }


    /**
     *
     * Content frame handler
     */
    private function frame(?string $view = null, array $data = [])
    {
        $user = request()->user();

        /* pull user's calendar instances and adapt ordering keys to calendarorder */
        $calendars = CalendarInstance::query()
            ->forUser($user)
            ->withUiMeta()
            ->ordered()
            ->get();

        return view('calendar.settings.index', [
            'view'      => $view,
            'data'      => $data,
            'calendars' => $calendars,
            'timezones' => config('timezones'),
        ]);
    }
}
