<?php

namespace App\Http\Controllers;

use App\Models\Family;
use App\Models\Person;
use App\Models\EthnicGroup;
use App\Models\Clan;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Services\InvitationService;
 

class FamilyDirectoryController extends Controller
{
    public function index(Request $request)
    {
        $families = Family::query()
            ->withCount('members')
            ->with(['owner'])
            ->latest()
            ->paginate(9)
            ->through(function (Family $family) {
                return [
                    'id' => $family->id,
                    'name' => $family->name,
                    'description' => $family->description,
                    'members_count' => $family->members_count,
                    'owner' => $family->owner?->name,
                    'owner_id' => $family->owner?->id,
                    'cover' => $family->settings['cover_photo'] ?? null,
                    'is_member' => auth()->check() ? $family->members()->where('people.user_id', auth()->id())->exists() : false,
                    'is_owner' => auth()->check() ? ((int) $family->created_by === (int) auth()->id() || $family->members()->wherePivot('role','owner')->where('people.user_id', auth()->id())->exists()) : false,
                    'created_at' => $family->created_at?->toFormattedDateString(),
                ];
            });

        $people = Person::query()
            ->latest('created_at')
            ->take(12)
            ->get()
            ->map(function (Person $person) {
                return [
                    'name' => trim("{$person->first_name} {$person->last_name}"),
                    'photo' => $person->photo_url,
                    'bio' => $person->bio,
                ];
            });

        return view('families.index', [
            'families' => $families,
            'people' => $people,
        ]);
    }

    public function create(Request $request)
    {
        return view('families.create', [
            'locations' => config('locations'),
            'defaultCountry' => config('familytree.default_country'),
        ]);
    }

    public function edit(Request $request, Family $family)
    {
        $this->authorizeManage($request, $family);

        $location = (array) ($family->settings['location'] ?? []);
        $members = $family->members()->get()->map(function (Person $p) {
            return [
                'id' => $p->id,
                'name' => trim("{$p->first_name} {$p->last_name}") ?: 'Member',
            ];
        });

        return view('families.edit', [
            'family' => $family,
            'locations' => config('locations'),
            'defaultCountry' => $location['country'] ?? config('familytree.default_country'),
            'members' => $members,
        ]);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'description' => ['nullable', 'string'],
            'country' => ['required', 'string', 'max:3'],
            'region' => ['nullable', 'string', 'max:255'],
            'district' => ['nullable', 'string', 'max:255'],
            'town' => ['nullable', 'string', 'max:255'],
            'ethnic_group_id' => ['nullable','integer','exists:ethnic_groups,id'],
            'clan_id' => ['nullable','integer','exists:clans,id'],
            'language' => ['nullable','string','max:255'],
            'cover_photo' => ['nullable','url'],
        ]);

        // Ensure selected clan belongs to given ethnic group (direct or via pivot), if provided
        if (!empty($data['clan_id']) && !empty($data['ethnic_group_id'])) {
            $belongs = Clan::query()
                ->where('id', $data['clan_id'])
                ->where(function($q) use ($data){
                    $q->where('ethnic_group_id', $data['ethnic_group_id'])
                      ->orWhereHas('ethnicGroups', function($r) use ($data){
                          $r->where('ethnic_group_id', $data['ethnic_group_id']);
                      });
                })
                ->exists();
            abort_unless($belongs, 422, 'Selected clan does not belong to the selected ethnic group.');
        }

        // Ensure ethnic group is valid for selected country
        if (!empty($data['ethnic_group_id'])) {
            $validGroup = EthnicGroup::query()
                ->where('id', $data['ethnic_group_id'])
                ->where('country_code', strtoupper($data['country']))
                ->exists();
            abort_unless($validGroup, 422, 'Selected ethnic group is not available for the chosen country.');
        }

        $slug = Str::slug($data['name']) . '-' . Str::random(6);

        $family = Family::create([
            'name' => $data['name'],
            'slug' => $slug,
            'description' => $data['description'] ?? null,
            'created_by' => $request->user()->id,
            'ethnic_group_id' => $data['ethnic_group_id'] ?? null,
            'clan_id' => $data['clan_id'] ?? null,
            'head_person_id' => null, // set after ensuring person exists below
            'settings' => [
                'location' => [
                    'country' => $data['country'],
                    'region' => $data['region'] ?? null,
                    'district' => $data['district'] ?? null,
                    'town' => $data['town'] ?? null,
                ],
                'cover_photo' => $data['cover_photo'] ?? null,
                'culture' => [
                    'language' => $data['language'] ?? null,
                ],
            ],
        ]);

        $user = $request->user();
        $person = $user->person;
        if (!$person) {
            $parts = preg_split('/\s+/', trim($user->name ?? ''), 2);
            $first = $parts[0] ?? ($user->name ?: 'User');
            $last = $parts[1] ?? '';
            $person = Person::create([
                'user_id' => $user->id,
                'first_name' => $first,
                'last_name' => $last,
            ]);
        }

        $family->members()->attach($person->id, [
            'role' => 'owner',
            'joined_at' => now(),
        ]);

        // Default family head to the owner who created it
        $family->update(['head_person_id' => $person->id]);

        return redirect()->route('families.index');
    }

    public function update(Request $request, Family $family)
    {
        $this->authorizeManage($request, $family);

        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'description' => ['nullable', 'string'],
            'country' => ['required', 'string', 'max:3'],
            'region' => ['nullable', 'string', 'max:255'],
            'district' => ['nullable', 'string', 'max:255'],
            'town' => ['nullable', 'string', 'max:255'],
            'ethnic_group_id' => ['nullable','integer','exists:ethnic_groups,id'],
            'clan_id' => ['nullable','integer','exists:clans,id'],
            'language' => ['nullable','string','max:255'],
            'cover_photo' => ['nullable','url'],
            'head_person_id' => ['nullable','integer','exists:people,id'],
        ]);

        // Ensure head (if provided) is a member of this family
        if (!empty($data['head_person_id'])) {
            $isMember = $family->members()->where('people.id', $data['head_person_id'])->exists();
            abort_unless($isMember, 422, 'Selected head must be a member of this family.');
        }

        // Ensure clan belongs to group (direct or via pivot)
        if (!empty($data['clan_id']) && !empty($data['ethnic_group_id'])) {
            $belongs = Clan::query()
                ->where('id', $data['clan_id'])
                ->where(function($q) use ($data){
                    $q->where('ethnic_group_id', $data['ethnic_group_id'])
                      ->orWhereHas('ethnicGroups', function($r) use ($data){
                          $r->where('ethnic_group_id', $data['ethnic_group_id']);
                      });
                })
                ->exists();
            abort_unless($belongs, 422, 'Selected clan does not belong to the selected ethnic group.');
        }

        // Ensure ethnic group is valid for selected country
        if (!empty($data['ethnic_group_id'])) {
            $validGroup = EthnicGroup::query()
                ->where('id', $data['ethnic_group_id'])
                ->where('country_code', strtoupper($data['country']))
                ->exists();
            abort_unless($validGroup, 422, 'Selected ethnic group is not available for the chosen country.');
        }

        $family->update([
            'name' => $data['name'],
            'description' => $data['description'] ?? null,
            'ethnic_group_id' => $data['ethnic_group_id'] ?? null,
            'clan_id' => $data['clan_id'] ?? null,
            'head_person_id' => $data['head_person_id'] ?? $family->head_person_id,
            'settings' => [
                'location' => [
                    'country' => $data['country'],
                    'region' => $data['region'] ?? null,
                    'district' => $data['district'] ?? null,
                    'town' => $data['town'] ?? null,
                ],
                'cover_photo' => $data['cover_photo'] ?? null,
                'culture' => [
                    'language' => $data['language'] ?? null,
                ],
            ],
        ]);

        return redirect()->route('families.index');
    }

    public function invite(Request $request, Family $family)
    {
        $this->authorizeInvite($request, $family);

        $invitations = $family->invitations()->latest()->take(20)->get();

        return view('families.invite', [
            'family' => $family,
            'invitations' => $invitations,
        ]);
    }

    public function sendInvite(Request $request, Family $family, InvitationService $invitations)
    {
        $this->authorizeInvite($request, $family);

        $generate = (bool) $request->boolean('generate');

        $rules = [
            'email' => ['nullable', 'email'],
            'phone' => ['nullable', 'string'],
        ];
        if (! $generate) {
            $rules['email'][] = 'required_without:phone';
            $rules['phone'][] = 'required_without:email';
        }
        $data = $request->validate($rules);

        if ($generate) {
            // Generate a token-only invitation for QR/link sharing
            $data = [];
        }

        $invitations->createInvitation($family, $data, $request->user());

        return redirect()->route('families.invite', $family)->with('status', 'Invitation sent');
    }

    private function authorizeInvite(Request $request, Family $family): void
    {
        $user = $request->user();
        $isOwner = $user && $family->members()
            ->wherePivot('role', 'owner')
            ->where('people.user_id', $user->id)
            ->exists();

        abort_unless($user && ($user->can('invitations.manage') || $isOwner), 403);
    }

    private function authorizeManage(Request $request, Family $family): void
    {
        $user = $request->user();
        $isOwner = $user && $family->members()
            ->wherePivot('role', 'owner')
            ->where('people.user_id', $user->id)
            ->exists();

        abort_unless($user && ($user->can('families.manage') || $isOwner), 403);
    }

 
}
