<?php

namespace App\Livewire;

use App\Enums\AppRole;
use App\Enums\PartnershipStatus;
use App\Models\Partnership;
use App\Models\Workspace;
use App\Models\WorkspaceMember;
use App\Queries\PartnershipsNeedingReminder;
use App\Services\WorkspaceBootstrapService;
use App\Services\WorkspaceContextResolver;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Url;
use Livewire\Component;

#[Layout('layouts.app')]
class CollabsBoard extends Component
{
    #[Url]
    public string $tab = 'pipeline';

    public string $search = '';

    public ?int $workspaceId = null;

    public string $workspaceRole = '';

    public bool $showModal = false;

    public ?int $editingId = null;

    public string $restaurant_name = '';

    public string $instagram_handle = '';

    public string $instagram_url = '';

    public string $formStatus = 'contacted';

    public ?string $scheduled_date = null;

    public ?string $scheduled_time = null;

    public ?int $guests = null;

    public string $notes = '';

    public string $location = '';

    public string $post_url = '';

    public ?int $managed_by_restaurant = null;

    /** When no restaurant members exist, assignee user id as text (matches React free-text fallback). */
    public string $managed_by_restaurant_manual = '';

    public ?int $inclusion_starters = null;

    public ?int $inclusion_mains = null;

    public ?int $inclusion_desserts = null;

    public ?int $inclusion_drinks = null;

    public string $inclusion_description = '';

    public function mount(
        WorkspaceBootstrapService $bootstrap,
        WorkspaceContextResolver $resolver,
    ): void {
        $user = Auth::user();
        $bootstrap->bootstrap($user);
        [$workspace, $role] = $resolver->resolve($user);
        if ($workspace === null || $role === null) {
            abort(500, 'Workspace could not be resolved.');
        }
        $this->workspaceId = $workspace->id;
        $this->workspaceRole = $role->value;
    }

    public function openCreate(): void
    {
        $workspace = Workspace::findOrFail($this->workspaceId);
        $this->authorize('createPartnership', $workspace);
        $this->editingId = null;
        $this->resetForm();
        $this->showModal = true;
    }

    public function openEdit(int $id): void
    {
        $p = Partnership::query()->findOrFail($id);
        $this->authorize('view', $p);
        $this->authorize('update', $p);
        $this->editingId = $id;
        $this->restaurant_name = $p->restaurant_name;
        $this->instagram_handle = (string) ($p->instagram_handle ?? '');
        $this->instagram_url = (string) ($p->instagram_url ?? '');
        $this->formStatus = $p->status instanceof PartnershipStatus ? $p->status->value : (string) $p->status;
        $this->scheduled_date = $p->scheduled_date?->format('Y-m-d');
        $this->scheduled_time = (string) ($p->scheduled_time ?? '');
        $this->guests = $p->guests;
        $this->notes = (string) ($p->notes ?? '');
        $this->location = (string) ($p->location ?? '');
        $this->post_url = (string) ($p->post_url ?? '');
        $this->managed_by_restaurant = $p->managed_by_restaurant;
        $this->managed_by_restaurant_manual = '';

        $members = WorkspaceMember::query()
            ->where('workspace_id', $this->workspaceId)
            ->where('role', AppRole::Restaurant->value)
            ->exists();
        if (! $members && $p->managed_by_restaurant !== null) {
            $this->managed_by_restaurant_manual = (string) $p->managed_by_restaurant;
            $this->managed_by_restaurant = null;
        }

        $inc = is_array($p->inclusions) ? $p->inclusions : [];
        $this->inclusion_starters = isset($inc['starters']) ? (int) $inc['starters'] : null;
        $this->inclusion_mains = isset($inc['mains']) ? (int) $inc['mains'] : null;
        $this->inclusion_desserts = isset($inc['desserts']) ? (int) $inc['desserts'] : null;
        $this->inclusion_drinks = isset($inc['drinks']) ? (int) $inc['drinks'] : null;
        $this->inclusion_description = (string) ($inc['description'] ?? '');
        $this->showModal = true;
    }

    public function closeModal(): void
    {
        $this->showModal = false;
        $this->editingId = null;
    }

    public function savePartnership(): void
    {
        $workspace = Workspace::findOrFail($this->workspaceId);

        $hasRestaurantMembers = WorkspaceMember::query()
            ->where('workspace_id', $this->workspaceId)
            ->where('role', AppRole::Restaurant->value)
            ->exists();

        $rules = [
            'restaurant_name' => 'required|string|max:255',
            'instagram_handle' => 'nullable|string|max:255',
            'instagram_url' => 'nullable|string|max:2048',
            'formStatus' => 'required|in:'.implode(',', array_column(PartnershipStatus::cases(), 'value')),
            'scheduled_date' => 'nullable|date',
            'scheduled_time' => 'nullable|string|max:64',
            'guests' => 'nullable|integer|min:1|max:9999',
            'notes' => 'nullable|string|max:10000',
            'location' => 'nullable|string|max:512',
            'post_url' => 'nullable|string|max:2048',
            'inclusion_starters' => 'nullable|integer|min:0|max:999',
            'inclusion_mains' => 'nullable|integer|min:0|max:999',
            'inclusion_desserts' => 'nullable|integer|min:0|max:999',
            'inclusion_drinks' => 'nullable|integer|min:0|max:999',
            'inclusion_description' => 'nullable|string|max:2000',
        ];

        if ($this->canManageWorkspace()) {
            if ($hasRestaurantMembers) {
                $rules['managed_by_restaurant'] = 'nullable|exists:users,id';
            } else {
                $rules['managed_by_restaurant_manual'] = 'nullable|string|max:19';
            }
        }

        $this->validate($rules);

        if ($hasRestaurantMembers) {
            $assigned = $this->managed_by_restaurant;
        } elseif ($this->canManageWorkspace() && trim((string) $this->managed_by_restaurant_manual) !== '') {
            $this->validate(['managed_by_restaurant_manual' => 'exists:users,id']);
            $assigned = (int) $this->managed_by_restaurant_manual;
        } else {
            $assigned = null;
        }

        if ($this->editingId) {
            $p = Partnership::query()->findOrFail($this->editingId);
            $this->authorize('update', $p);
        } else {
            $this->authorize('createPartnership', $workspace);
            $p = new Partnership;
            $p->workspace_id = $workspace->id;
            $p->created_by = Auth::id();
        }

        $p->restaurant_name = $this->restaurant_name;
        $p->instagram_handle = $this->instagram_handle !== '' ? $this->instagram_handle : null;
        $p->instagram_url = $this->instagram_url !== '' ? $this->instagram_url : null;
        $p->status = PartnershipStatus::from($this->formStatus);
        $p->scheduled_date = $this->scheduled_date ?: null;
        $p->scheduled_time = $this->scheduled_time !== '' ? $this->scheduled_time : null;
        $p->guests = $this->guests;
        $p->notes = $this->notes !== '' ? $this->notes : null;
        $p->location = $this->location !== '' ? $this->location : null;
        $p->post_url = $this->post_url !== '' ? $this->post_url : null;
        if ($this->canManageWorkspace()) {
            $p->managed_by_restaurant = $assigned;
        } elseif (! $this->editingId) {
            $p->managed_by_restaurant = null;
        }

        $p->inclusions = $this->buildInclusionsPayload();

        $p->save();
        $this->closeModal();
    }

    public function quickAlreadyWent(): void
    {
        $this->formStatus = PartnershipStatus::Completed->value;
        $this->savePartnership();
    }

    public function quickArchive(): void
    {
        $this->formStatus = PartnershipStatus::Archived->value;
        $this->savePartnership();
    }

    public function deleteModalPartnership(): void
    {
        if ($this->editingId === null) {
            return;
        }
        $id = $this->editingId;
        $this->deletePartnership($id);
        $this->closeModal();
    }

    private function canManageWorkspace(): bool
    {
        $workspace = Workspace::findOrFail($this->workspaceId);

        return Auth::user()->can('createPartnership', $workspace);
    }

    /**
     * @return array<string, mixed>|null
     */
    private function buildInclusionsPayload(): ?array
    {
        $payload = [];
        $map = [
            'starters' => 'inclusion_starters',
            'mains' => 'inclusion_mains',
            'desserts' => 'inclusion_desserts',
            'drinks' => 'inclusion_drinks',
        ];
        foreach ($map as $key => $prop) {
            $v = $this->{$prop};
            if ($v !== null && $v !== '') {
                $payload[$key] = (int) $v;
            }
        }
        if ($this->inclusion_description !== '') {
            $payload['description'] = $this->inclusion_description;
        }

        return $payload === [] ? null : $payload;
    }

    public function deletePartnership(int $id): void
    {
        $p = Partnership::query()->findOrFail($id);
        $this->authorize('delete', $p);
        $p->delete();
    }

    public function moveToStatus(int $partnershipId, string $status): void
    {
        $statusEnum = PartnershipStatus::from($status);
        $p = Partnership::query()->findOrFail($partnershipId);
        $this->authorize('update', $p);
        if ($p->status === $statusEnum) {
            return;
        }
        $p->update(['status' => $statusEnum->value]);
    }

    public function render(): View
    {
        $user = Auth::user();
        $workspace = Workspace::query()->findOrFail($this->workspaceId);

        $query = Partnership::query()->visibleTo($user, $workspace);

        if ($this->tab === 'pipeline') {
            $query->whereIn('status', [
                PartnershipStatus::Upcoming->value,
                PartnershipStatus::Confirmed->value,
                PartnershipStatus::Contacted->value,
            ]);
        } else {
            $query->whereIn('status', [
                PartnershipStatus::Completed->value,
                PartnershipStatus::Archived->value,
            ]);
        }

        if ($this->search !== '') {
            $term = '%'.addcslashes($this->search, '%_\\').'%';
            $query->where(function ($q) use ($term): void {
                $q->where('restaurant_name', 'like', $term)
                    ->orWhere('instagram_handle', 'like', $term)
                    ->orWhere('location', 'like', $term)
                    ->orWhere('notes', 'like', $term);
            });
        }

        $partnerships = $query->orderByDesc('updated_at')->get();

        if ($this->tab === 'pipeline') {
            $upcoming = $partnerships
                ->filter(fn (Partnership $p) => $p->status === PartnershipStatus::Upcoming)
                ->sortBy(fn (Partnership $p) => $p->scheduled_date?->timestamp ?? PHP_INT_MAX)
                ->values();
            $confirmed = $partnerships->filter(fn (Partnership $p) => $p->status === PartnershipStatus::Confirmed)->values();
            $contacted = $partnerships->filter(fn (Partnership $p) => $p->status === PartnershipStatus::Contacted)->values();
        } else {
            $upcoming = collect();
            $confirmed = collect();
            $contacted = collect();
        }

        $completed = $this->tab === 'history'
            ? $partnerships->filter(fn (Partnership $p) => $p->status === PartnershipStatus::Completed)->values()
            : collect();
        $archived = $this->tab === 'history'
            ? $partnerships->filter(fn (Partnership $p) => $p->status === PartnershipStatus::Archived)->values()
            : collect();

        $activePartnershipCount = Partnership::query()
            ->visibleTo($user, $workspace)
            ->whereIn('status', [
                PartnershipStatus::Upcoming->value,
                PartnershipStatus::Confirmed->value,
                PartnershipStatus::Contacted->value,
            ])
            ->count();

        $canManage = $user->can('createPartnership', $workspace);

        $restaurantMembers = WorkspaceMember::query()
            ->where('workspace_id', $workspace->id)
            ->where('role', AppRole::Restaurant->value)
            ->with('user')
            ->get();

        $editingPartnership = $this->editingId !== null
            ? Partnership::query()->find($this->editingId)
            : null;

        $modalCanDelete = $this->showModal
            && $editingPartnership !== null
            && $user->can('delete', $editingPartnership);

        $pipelineStatuses = [
            PartnershipStatus::Upcoming->value,
            PartnershipStatus::Confirmed->value,
            PartnershipStatus::Contacted->value,
        ];
        $showQuickAlreadyWent = $this->showModal
            && $this->editingId !== null
            && in_array($this->formStatus, $pipelineStatuses, true);
        $showQuickArchive = $this->showModal
            && $this->editingId !== null
            && $this->formStatus !== PartnershipStatus::Archived->value;

        $reminderPartnerships = collect();
        if ($this->tab === 'pipeline') {
            $startOfToday = now()->startOfDay();
            $reminderPartnerships = $upcoming
                ->filter(fn (Partnership $p) => PartnershipsNeedingReminder::matches($p, $startOfToday))
                ->values();
        }

        return view('livewire.collabs-board', [
            'workspace' => $workspace,
            'upcoming' => $upcoming,
            'confirmed' => $confirmed,
            'contacted' => $contacted,
            'completed' => $completed,
            'archived' => $archived,
            'activePartnershipCount' => $activePartnershipCount,
            'canManage' => $canManage,
            'restaurantMembers' => $restaurantMembers,
            'statusOptions' => PartnershipStatus::cases(),
            'modalCanDelete' => $modalCanDelete,
            'showQuickAlreadyWent' => $showQuickAlreadyWent,
            'showQuickArchive' => $showQuickArchive,
            'reminderPartnerships' => $reminderPartnerships,
        ]);
    }

    private function resetForm(): void
    {
        $this->restaurant_name = '';
        $this->instagram_handle = '';
        $this->instagram_url = '';
        $this->formStatus = PartnershipStatus::Contacted->value;
        $this->scheduled_date = null;
        $this->scheduled_time = null;
        $this->guests = null;
        $this->notes = '';
        $this->location = '';
        $this->post_url = '';
        $this->managed_by_restaurant = null;
        $this->managed_by_restaurant_manual = '';
        $this->inclusion_starters = null;
        $this->inclusion_mains = null;
        $this->inclusion_desserts = null;
        $this->inclusion_drinks = null;
        $this->inclusion_description = '';
    }
}
