<?php

namespace App\Http\Controllers\Owner;

use App\Http\Controllers\Controller;
use App\Models\ArtistItem;
use App\Models\Customer;
use App\Models\GiftItem;
use App\Models\MariachiGroup;
use App\Models\OtherCostItem;
use App\Models\Serenata;
use App\Models\SerenataPackage;
use App\Support\PhoneNumber;
use App\Support\MariachiCatalogManager;
use App\Support\OwnerWorkspace;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class MariachiGroupController extends Controller
{
    public function index(Request $request)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        $canManage = $organizationId > 0;

        if ($canManage) {
            MariachiGroup::ensureDefaultForOrganization($organizationId);
        }

        $groups = $canManage
            ? MariachiGroup::query()
                ->where('organization_id', $organizationId)
                ->orderBy('sort_order')
                ->orderBy('name')
                ->get()
            : collect();

        return view('content.owner.settings.mariachi-groups.index', [
            'canManageGroups' => $canManage,
            'groups' => $groups,
            'stats' => [
                'total' => $groups->count(),
                'active' => $groups->where('is_active', true)->count(),
                'default' => $groups->where('is_default', true)->count(),
            ],
        ]);
    }

    public function show(Request $request, MariachiGroup $mariachiGroup)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        if (
            $organizationId <= 0
            || $mariachiGroup->organization_id !== $organizationId
        ) {
            abort(404);
        }

        OwnerWorkspace::setActiveGroupId($request, (int) $mariachiGroup->id);

        $mariachiGroup->ensureOwnCatalog();
        $perPage = 10;
        $queryParams = $request->query();
        $packageSearch = trim((string) $request->query('packages_q', ''));
        $packageStatus = trim((string) $request->query('packages_status', ''));
        $giftSearch = trim((string) $request->query('gifts_q', ''));
        $giftType = trim((string) $request->query('gifts_type', ''));
        $giftStatus = trim((string) $request->query('gifts_status', ''));
        $artistSearch = trim((string) $request->query('artists_q', ''));
        $artistType = trim((string) $request->query('artists_type', ''));
        $artistStatus = trim((string) $request->query('artists_status', ''));
        $otherCostSearch = trim((string) $request->query('other_costs_q', ''));
        $otherCostStatus = trim((string) $request->query('other_costs_status', ''));
        $serenataSearch = trim((string) $request->query('serenatas_q', ''));
        $serenataStatus = trim((string) $request->query('serenatas_status', ''));
        $serenataPaymentStatus = trim((string) $request->query('serenatas_payment', ''));
        $customerSearch = trim((string) $request->query('customers_q', ''));
        $customerStatus = trim((string) $request->query('customers_status', ''));

        $packagesQuery = $mariachiGroup->serenataPackages();

        if ($packageSearch !== '') {
            $packagesQuery->where(function ($query) use ($packageSearch) {
                $like = '%' . $packageSearch . '%';
                $query
                    ->where('name', 'like', $like)
                    ->orWhere('city', 'like', $like);
            });
        }

        if ($packageStatus !== '') {
            $packagesQuery->where('is_active', $packageStatus === '1');
        }

        $packages = $packagesQuery
            ->orderByDesc('is_default')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->paginate($perPage, ['*'], 'packages_page')
            ->appends($queryParams)
            ->fragment('group-packages');

        $giftItemsQuery = $mariachiGroup->giftItems();

        if ($giftSearch !== '') {
            $giftItemsQuery->where('name', 'like', '%' . $giftSearch . '%');
        }

        if (in_array($giftType, ['included', 'additional'], true)) {
            $giftItemsQuery->where('type', $giftType);
        }

        if ($giftStatus !== '') {
            $giftItemsQuery->where('is_active', $giftStatus === '1');
        }

        $giftItems = $giftItemsQuery
            ->orderBy('type')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->paginate($perPage, ['*'], 'gifts_page')
            ->appends($queryParams)
            ->fragment('group-gifts');

        $artistItemsQuery = $mariachiGroup->artistItems();

        if ($artistSearch !== '') {
            $artistItemsQuery->where('name', 'like', '%' . $artistSearch . '%');
        }

        if (in_array($artistType, ['included', 'additional'], true)) {
            $artistItemsQuery->where('type', $artistType);
        }

        if ($artistStatus !== '') {
            $artistItemsQuery->where('is_active', $artistStatus === '1');
        }

        $artistItems = $artistItemsQuery
            ->orderBy('type')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->paginate($perPage, ['*'], 'artists_page')
            ->appends($queryParams)
            ->fragment('group-artists');

        $otherCostItemsQuery = $mariachiGroup->otherCostItems();

        if ($otherCostSearch !== '') {
            $otherCostItemsQuery->where('name', 'like', '%' . $otherCostSearch . '%');
        }

        if ($otherCostStatus !== '') {
            $otherCostItemsQuery->where('is_active', $otherCostStatus === '1');
        }

        $otherCostItems = $otherCostItemsQuery
            ->orderBy('sort_order')
            ->orderBy('name')
            ->paginate($perPage, ['*'], 'other_costs_page')
            ->appends($queryParams)
            ->fragment('group-other-costs');

        $packageCatalogGifts = $mariachiGroup->giftItems()
            ->where('is_active', true)
            ->orderBy('type')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get(['id', 'code', 'name', 'type', 'internal_cost', 'base_price']);

        $packageCatalogArtists = $mariachiGroup->artistItems()
            ->where('is_active', true)
            ->orderBy('type')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get(['id', 'code', 'name', 'type', 'internal_cost', 'base_price']);

        $packageCatalogOtherCosts = $mariachiGroup->otherCostItems()
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get(['id', 'code', 'name', 'internal_cost', 'base_price']);

        $serenatasQuery = Serenata::query()
            ->where('organization_id', $organizationId)
            ->where('mariachi_group_id', $mariachiGroup->id);

        if ($serenataSearch !== '') {
            $serenatasQuery->where(function ($query) use ($serenataSearch) {
                $like = '%' . $serenataSearch . '%';
                $query
                    ->where('code', 'like', $like)
                    ->orWhere('payer_name', 'like', $like)
                    ->orWhere('to_name', 'like', $like)
                    ->orWhere('reason', 'like', $like)
                    ->orWhere('service_address', 'like', $like);
            });
        }

        if ($serenataStatus !== '') {
            $serenatasQuery->where('service_status', $serenataStatus);
        }

        if ($serenataPaymentStatus !== '') {
            $serenatasQuery->where('payment_status', $serenataPaymentStatus);
        }

        $serenatas = $serenatasQuery
            ->orderByDesc('event_date')
            ->orderByDesc('event_time')
            ->paginate($perPage, ['*'], 'serenatas_page')
            ->appends($queryParams)
            ->fragment('group-serenatas');

        $customersQuery = Customer::query()
            ->where('organization_id', $organizationId)
            ->where('mariachi_group_id', $mariachiGroup->id);

        if ($customerSearch !== '') {
            $customersQuery->where(function ($query) use ($customerSearch) {
                $like = '%' . $customerSearch . '%';
                $phoneDigits = PhoneNumber::digits($customerSearch);
                $query
                    ->where('name', 'like', $like)
                    ->orWhere('email', 'like', $like)
                    ->orWhere('mobile', 'like', $like)
                    ->orWhere('address_line_1', 'like', $like);

                if ($phoneDigits !== '') {
                    $query->orWhereRaw(
                        "REPLACE(REPLACE(REPLACE(COALESCE(mobile, ''), ' ', ''), '-', ''), '+', '') like ?",
                        ['%' . $phoneDigits . '%']
                    );
                }
            });
        }

        if ($customerStatus !== '') {
            $customersQuery->where('is_active', $customerStatus === '1');
        }

        $customers = $customersQuery
            ->orderByDesc('id')
            ->paginate($perPage, ['*'], 'customers_page')
            ->appends($queryParams)
            ->fragment('group-customers');

        $serenataStatusOptions = Serenata::query()
            ->where('organization_id', $organizationId)
            ->where('mariachi_group_id', $mariachiGroup->id)
            ->whereNotNull('service_status')
            ->where('service_status', '!=', '')
            ->distinct()
            ->orderBy('service_status')
            ->pluck('service_status')
            ->values();

        $serenataPaymentOptions = Serenata::query()
            ->where('organization_id', $organizationId)
            ->where('mariachi_group_id', $mariachiGroup->id)
            ->whereNotNull('payment_status')
            ->where('payment_status', '!=', '')
            ->distinct()
            ->orderBy('payment_status')
            ->pluck('payment_status')
            ->values();

        $stats = [
            'serenatas' => (int) Serenata::query()->where('organization_id', $organizationId)->where('mariachi_group_id', $mariachiGroup->id)->count(),
            'clientes' => (int) Customer::query()->where('organization_id', $organizationId)->where('mariachi_group_id', $mariachiGroup->id)->count(),
            'paquetes' => (int) $mariachiGroup->serenataPackages()->count(),
            'obsequios' => (int) $mariachiGroup->giftItems()->count(),
            'artistas' => (int) $mariachiGroup->artistItems()->count(),
            'otros_costos' => (int) $mariachiGroup->otherCostItems()->count(),
            'total_cobrado' => (float) Serenata::query()->where('organization_id', $organizationId)->where('mariachi_group_id', $mariachiGroup->id)->sum('total_charged'),
            'ultima_serenata' => Serenata::query()->where('organization_id', $organizationId)->where('mariachi_group_id', $mariachiGroup->id)->latest('event_date')->latest('event_time')->value('event_date'),
        ];

        return view('content.owner.settings.mariachi-groups.show', [
            'group' => $mariachiGroup,
            'stats' => $stats,
            'packages' => $packages,
            'giftItems' => $giftItems,
            'artistItems' => $artistItems,
            'otherCostItems' => $otherCostItems,
            'packageCatalogGifts' => $packageCatalogGifts,
            'packageCatalogArtists' => $packageCatalogArtists,
            'packageCatalogOtherCosts' => $packageCatalogOtherCosts,
            'serenatas' => $serenatas,
            'customers' => $customers,
            'serenataStatusOptions' => $serenataStatusOptions,
            'serenataPaymentOptions' => $serenataPaymentOptions,
        ]);
    }

    public function store(Request $request)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        if ($organizationId <= 0) {
            return redirect()->route('owner.settings.mariachi-groups')->withErrors([
                'name' => 'Primero debes tener una organización asignada.',
            ]);
        }

        $validated = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'description' => ['nullable', 'string', 'max:255'],
            'is_active' => ['required', 'boolean'],
            'is_default' => ['required', 'boolean'],
            'sort_order' => ['nullable', 'integer', 'min:0', 'max:9999'],
        ]);

        $cloneSource = MariachiGroup::query()
            ->where('organization_id', $organizationId)
            ->orderByDesc('is_default')
            ->orderBy('sort_order')
            ->orderBy('id')
            ->first();

        $baseCode = Str::slug((string) $validated['name'], '_');
        $baseCode = $baseCode !== '' ? $baseCode : 'grupo';
        $code = $baseCode;
        $counter = 1;

        while (
            MariachiGroup::query()
                ->where('organization_id', $organizationId)
                ->where('code', $code)
                ->exists()
        ) {
            $counter++;
            $code = $baseCode . '_' . $counter;
        }

        if ((bool) $validated['is_default']) {
            MariachiGroup::query()
                ->where('organization_id', $organizationId)
                ->update(['is_default' => false]);
        }

        $group = MariachiGroup::create([
            'organization_id' => $organizationId,
            'code' => $code,
            'name' => $validated['name'],
            'description' => trim((string) ($validated['description'] ?? '')) ?: null,
            'is_active' => (bool) $validated['is_active'],
            'is_default' => (bool) $validated['is_default'],
            'sort_order' => (int) ($validated['sort_order'] ?? 100),
        ]);

        if ($cloneSource) {
            $group->cloneCatalogFrom($cloneSource);
        } else {
            MariachiCatalogManager::bootstrapBaseCatalog($group);
        }

        return redirect()->route('owner.settings.mariachi-groups')->with('status', 'Grupo creado correctamente.');
    }

    public function update(Request $request, MariachiGroup $mariachiGroup)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        if ($organizationId <= 0 || $mariachiGroup->organization_id !== $organizationId) {
            abort(404);
        }

        $validated = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'description' => ['nullable', 'string', 'max:255'],
            'is_active' => ['required', 'boolean'],
            'is_default' => ['required', 'boolean'],
            'sort_order' => ['nullable', 'integer', 'min:0', 'max:9999'],
        ]);

        if ((bool) $validated['is_default']) {
            MariachiGroup::query()
                ->where('organization_id', $organizationId)
                ->whereKeyNot($mariachiGroup->id)
                ->update(['is_default' => false]);
        }

        $mariachiGroup->update([
            'name' => $validated['name'],
            'description' => trim((string) ($validated['description'] ?? '')) ?: null,
            'is_active' => (bool) $validated['is_active'],
            'is_default' => (bool) $validated['is_default'],
            'sort_order' => (int) ($validated['sort_order'] ?? $mariachiGroup->sort_order),
        ]);

        if (!$mariachiGroup->is_default) {
            MariachiGroup::ensureDefaultForOrganization($organizationId);
        }

        return redirect()->route('owner.settings.mariachi-groups')->with('status', 'Grupo actualizado correctamente.');
    }

    public function deactivate(Request $request, MariachiGroup $mariachiGroup)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        if ($organizationId <= 0 || $mariachiGroup->organization_id !== $organizationId) {
            abort(404);
        }

        $newState = !$mariachiGroup->is_active;

        if (!$newState) {
            $activeGroupsQuery = MariachiGroup::query()
                ->where('organization_id', $organizationId)
                ->where('is_active', true);

            if ((clone $activeGroupsQuery)->count() <= 1) {
                return back()->withErrors([
                    'name' => 'Debe existir al menos un grupo activo en la organización.',
                ]);
            }

            if ($mariachiGroup->is_default) {
                $replacement = (clone $activeGroupsQuery)
                    ->whereKeyNot($mariachiGroup->id)
                    ->orderByDesc('is_default')
                    ->orderBy('sort_order')
                    ->orderBy('id')
                    ->first();

                if ($replacement) {
                    MariachiGroup::query()
                        ->where('organization_id', $organizationId)
                        ->whereKey($replacement->id)
                        ->update(['is_default' => true]);
                }

                $mariachiGroup->is_default = false;
            }
        }

        $mariachiGroup->is_active = $newState;
        $mariachiGroup->save();

        MariachiGroup::ensureDefaultForOrganization($organizationId);

        return back()->with('status', $mariachiGroup->is_active
            ? 'Grupo activado correctamente.'
            : 'Grupo inactivado correctamente.');
    }

    public function destroy(Request $request, MariachiGroup $mariachiGroup)
    {
        $organizationId = (int) ($request->user()->organization_id ?? 0);
        if ($organizationId <= 0 || $mariachiGroup->organization_id !== $organizationId) {
            abort(404);
        }

        return back()->withErrors([
            'name' => 'Los grupos musicales ya no se eliminan. Usa la opción de activar o inactivar.',
        ]);
    }
}
