<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\MariachiGroup;
use App\Models\Organization;
use App\Models\Role;
use App\Models\User;
use App\Support\Authorization\PermissionCatalog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\Rule;
use Spatie\Permission\PermissionRegistrar;

class OrganizationController extends Controller
{
    private function linkedDataCounts(int $organizationId): array
    {
        $tables = [
            'users',
            'roles',
            'model_has_roles',
            'model_has_permissions',
            'gift_items',
            'artist_items',
            'other_cost_items',
            'serenatas',
            'customers',
            'serenata_status_histories',
            'payment_methods',
            'serenata_payments',
            'external_partners',
            'mariachi_groups',
            'quote_transport_rules',
            'serenata_route_plans',
            'serenata_packages',
        ];

        $counts = [];
        foreach ($tables as $table) {
            if (!Schema::hasTable($table) || !Schema::hasColumn($table, 'organization_id')) {
                continue;
            }

            $count = (int) DB::table($table)->where('organization_id', $organizationId)->count();
            if ($count > 0) {
                $counts[$table] = $count;
            }
        }

        return $counts;
    }

    private function hasLinkedData(int $organizationId): bool
    {
        return !empty($this->linkedDataCounts($organizationId));
    }

    private function reassignOrganizationData(int $sourceOrganizationId, int $targetOrganizationId): void
    {
        $tables = [
            'users',
            'roles',
            'model_has_roles',
            'model_has_permissions',
            'gift_items',
            'artist_items',
            'other_cost_items',
            'serenatas',
            'customers',
            'serenata_status_histories',
            'payment_methods',
            'serenata_payments',
            'external_partners',
            'mariachi_groups',
            'quote_transport_rules',
            'serenata_route_plans',
            'serenata_packages',
        ];

        foreach ($tables as $table) {
            if (!Schema::hasTable($table) || !Schema::hasColumn($table, 'organization_id')) {
                continue;
            }

            DB::table($table)
                ->where('organization_id', $sourceOrganizationId)
                ->update(['organization_id' => $targetOrganizationId]);
        }
    }

    public function index()
    {
        $mariachiGroups = Organization::with('ownerUser')->orderByDesc('id')->get()->map(function (Organization $group) {
            $group->has_linked_data = $this->hasLinkedData((int) $group->id);
            return $group;
        });
        $users = User::where('is_active', true)
            ->where('role', User::ROLE_CLIENT)
            ->orderBy('name')
            ->get();

        $stats = [
            'total' => $mariachiGroups->count(),
            'active' => $mariachiGroups->where('is_active', true)->count(),
            'inactive' => $mariachiGroups->where('is_active', false)->count(),
            'with_owner' => $mariachiGroups->filter(fn(Organization $mariachiGroup) => !empty($mariachiGroup->owner_user_id))->count(),
        ];

        return view('content.admin.organizations.index', [
            'mariachiGroups' => $mariachiGroups,
            'users' => $users,
            'stats' => $stats,
        ]);
    }

    public function create()
    {
        $users = User::where('is_active', true)
            ->where('role', User::ROLE_CLIENT)
            ->orderBy('name')
            ->get();

        return view('content.admin.organizations.create', ['users' => $users]);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'contact_phone' => ['nullable', 'string', 'max:30'],
            'city' => ['nullable', 'string', 'max:120'],
            'country_code' => ['required', 'string', 'size:2'],
            'notes' => ['nullable', 'string', 'max:1500'],
            'owner_user_id' => ['nullable', Rule::exists('users', 'id')->where('role', User::ROLE_CLIENT)],
            'is_active' => ['required', 'boolean'],
        ]);
        $validated['country_code'] = strtoupper((string) $validated['country_code']);

        $validated['entity_type'] = 'ORGANIZATION';

        $mariachiGroup = Organization::create($validated);
        MariachiGroup::ensureDefaultForOrganization((int) $mariachiGroup->id);
        $ownerRole = Role::query()->firstOrCreate(
            [
                'code' => PermissionCatalog::ownerSystemRoleCode((int) $mariachiGroup->id),
                'guard_name' => 'web',
            ],
            [
                'name' => 'OWNER',
                'organization_id' => (int) $mariachiGroup->id,
                'is_system' => true,
                'is_active' => true,
            ]
        );
        $ownerRole->syncPermissions(PermissionCatalog::permissionNamesForPanel(PermissionCatalog::PANEL_OWNER));

        if (!empty($validated['owner_user_id'])) {
            $ownerUser = User::query()->find($validated['owner_user_id']);
            $ownerUser?->update([
                'organization_id' => $mariachiGroup->id,
                'has_all_mariachi_groups' => true,
            ]);

            if ($ownerUser) {
                app(PermissionRegistrar::class)->setPermissionsTeamId($mariachiGroup->id);
                $ownerUser->syncRoles([$ownerRole]);
            }
        }

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

    public function update(Request $request, Organization $organization)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'contact_phone' => ['nullable', 'string', 'max:30'],
            'city' => ['nullable', 'string', 'max:120'],
            'country_code' => ['required', 'string', 'size:2'],
            'notes' => ['nullable', 'string', 'max:1500'],
            'owner_user_id' => ['nullable', Rule::exists('users', 'id')->where('role', User::ROLE_CLIENT)],
            'is_active' => ['required', 'boolean'],
        ]);
        $validated['country_code'] = strtoupper((string) $validated['country_code']);

        $organization->update($validated);
        MariachiGroup::ensureDefaultForOrganization((int) $organization->id);
        $ownerRole = Role::query()->firstOrCreate(
            [
                'code' => PermissionCatalog::ownerSystemRoleCode((int) $organization->id),
                'guard_name' => 'web',
            ],
            [
                'name' => 'OWNER',
                'organization_id' => (int) $organization->id,
                'is_system' => true,
                'is_active' => true,
            ]
        );
        $ownerRole->syncPermissions(PermissionCatalog::permissionNamesForPanel(PermissionCatalog::PANEL_OWNER));

        if (!empty($validated['owner_user_id'])) {
            $ownerUser = User::query()->find($validated['owner_user_id']);
            $ownerUser?->update([
                'organization_id' => $organization->id,
                'has_all_mariachi_groups' => true,
            ]);

            if ($ownerUser) {
                app(PermissionRegistrar::class)->setPermissionsTeamId($organization->id);
                $ownerUser->syncRoles([$ownerRole]);
            }
        }

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

    public function deactivate(Organization $organization)
    {
        $organization->update(['is_active' => false]);

        return redirect()->route('admin.mariachi-groups.index')->with('status', 'Grupo mariachi desactivado.');
    }

    public function merge(Request $request, Organization $organization)
    {
        $validated = $request->validate([
            'target_group_id' => ['required', 'integer', 'different:' . $organization->id, Rule::exists('organizations', 'id')],
        ]);

        $targetGroup = Organization::query()->findOrFail((int) $validated['target_group_id']);

        DB::transaction(function () use ($organization, $targetGroup): void {
            $sourceId = (int) $organization->id;
            $targetId = (int) $targetGroup->id;

            $this->reassignOrganizationData($sourceId, $targetId);

            $targetNotes = trim((string) ($targetGroup->notes ?? ''));
            $appendNote = 'Fusionado desde grupo #' . $sourceId . ' - ' . now()->format('Y-m-d H:i:s');
            $targetGroup->update([
                'notes' => trim($targetNotes . PHP_EOL . $appendNote),
            ]);

            $organization->update([
                'is_active' => false,
                'owner_user_id' => null,
                'notes' => trim((string) ($organization->notes ?? '') . PHP_EOL . 'Fusionado en grupo #' . $targetId . ' - ' . now()->format('Y-m-d H:i:s')),
            ]);
        });

        return redirect()->route('admin.mariachi-groups.index')->with('status', 'Grupos fusionados correctamente.');
    }

    public function destroy(Organization $organization)
    {
        $linkedData = $this->linkedDataCounts((int) $organization->id);
        if (!empty($linkedData)) {
            $detail = collect($linkedData)
                ->map(fn (int $count, string $table) => $table . ': ' . $count)
                ->implode(' | ');

            return redirect()->route('admin.mariachi-groups.index')->withErrors([
                'name' => 'No se puede eliminar el grupo porque tiene datos vinculados. Usa desactivar o fusionar. Detalle: ' . $detail,
            ]);
        }

        $organization->delete();

        return redirect()->route('admin.mariachi-groups.index')->with('status', 'Grupo mariachi eliminado definitivamente.');
    }
}
