<?php

namespace App\Http\Livewire\Calls;

use App\Models\Account;
use App\Models\Call;
use App\Models\CallTranslation;
use App\Models\Locations\Location;
use App\Models\Transaction;
use App\Services\CallCreditService;
use Illuminate\Support\Facades\App;
use Livewire\Component;
use WireUi\Traits\WireUiActions;

class Create extends Component
{
    use WireUiActions;

    public string $content = '';
    public ?string $till = null;
    public ?int $tagId = null;
    public bool $isPublic = false;

    // Location fields
    public $country = null;
    public $division = null;
    public $city = null;
    public $district = null;

    public bool $showModal = false;
    public bool $showNoCreditsModal = false;

    protected $listeners = [
        'countryToParent',
        'divisionToParent',
        'cityToParent',
        'districtToParent',
        'callTagSelected',
        'callTagCleared',
    ];

    protected function messages(): array
    {
        return [
            'till.required'       => __('Expire date is required.'),
            'till.date'           => __('Expire date must be a valid date.'),
            'till.after'          => __('Expire date must be in the future.'),
            'till.before_or_equal'=> __('Expire date exceeds the maximum allowed period.'),
        ];
    }

    public function getTillMaxDays(): ?int
    {
        $activeProfileType = session('activeProfileType');
        if ($activeProfileType && $activeProfileType !== \App\Models\User::class) {
            return timebank_config('calls.till_max_days_non_user');
        }
        return timebank_config('calls.till_max_days');
    }

protected function rules(): array
    {
        $tillMaxDays = $this->getTillMaxDays();
        $tillRule = 'required|date|after:today';
        if ($tillMaxDays !== null) {
            $tillRule .= '|before_or_equal:' . now()->addDays($tillMaxDays)->format('Y-m-d');
        }

        return [
            'content' => ['required', 'string', 'max:' . timebank_config('calls.content_max_input', 200)],
            'till'    => $tillRule,
            'tagId'   => 'required|integer|exists:taggable_tags,tag_id',
            'country' => 'required|integer|exists:countries,id',
            'city'    => 'nullable|integer|exists:cities,id',
            'district'=> 'nullable|integer|exists:districts,id',
        ];
    }

    public function openModal(): void
    {
        $activeProfileType = session('activeProfileType');

        if (!$activeProfileType || !in_array($activeProfileType, [
            \App\Models\User::class,
            \App\Models\Organization::class,
            \App\Models\Bank::class,
        ])) {
            abort(403, __('Only platform profiles (User, Organization, Bank) can create Calls.'));
        }

        $activeProfileId = session('activeProfileId');
        if (!CallCreditService::profileHasCredits($activeProfileType, (int) $activeProfileId)) {
            $this->showNoCreditsModal = true;
            return;
        }

        $this->reset(['content', 'till', 'tagId', 'country', 'division', 'city', 'district', 'isPublic']);
        $this->resetValidation();

        // Pre-fill expiry date from platform config default
        $defaultExpiryDays = timebank_config('calls.default_expiry_days');
        if ($defaultExpiryDays) {
            $this->till = now()->addDays($defaultExpiryDays)->format('Y-m-d');
        }

        // Pre-fill location from the callable profile's primary location
        $profile = $activeProfileType::find(session('activeProfileId'));
        $location = $profile?->locations()->with(['country', 'division', 'city', 'district'])->first();
        if ($location) {
            $this->country  = $location->country_id;
            $this->division = $location->division_id;
            $this->city     = $location->city_id;
            $this->district = $location->district_id;
        }

        $this->showModal = true;
    }

    /**
     * Called by the CallSkillInput child component when a tag is selected or created.
     */
    public function callTagSelected(int $tagId): void
    {
        $this->tagId = $tagId;
        $this->resetValidation('tagId');
    }

    /**
     * Called by the CallSkillInput child component when the tag input is cleared.
     */
    public function callTagCleared(): void
    {
        $this->tagId = null;
    }

    public function countryToParent($value): void  { $this->country  = $value ?: null; }
    public function divisionToParent($value): void { $this->division = $value ?: null; }
    public function cityToParent($value): void     { $this->city     = $value ?: null; }
    public function districtToParent($value): void { $this->district = $value ?: null; }

    public function save(): void
    {
        $activeProfileType = session('activeProfileType');

        if (!$activeProfileType || !in_array($activeProfileType, [
            \App\Models\User::class,
            \App\Models\Organization::class,
            \App\Models\Bank::class,
        ])) {
            abort(403);
        }

        $this->validate();

        // Resolve or create a standalone Location record
        $locationId = null;
        if ($this->country || $this->city) {
            $attributes = array_filter([
                'country_id'  => $this->country  ?: null,
                'division_id' => $this->division ?: null,
                'city_id'     => $this->city     ?: null,
                'district_id' => $this->district ?: null,
            ]);
            $location = Location::whereNull('locatable_id')
                ->whereNull('locatable_type')
                ->where($attributes)
                ->first();
            if (!$location) {
                $location = new Location($attributes);
                $location->save();
            }
            $locationId = $location->id;
        }

        $call = Call::create([
            'callable_id'   => session('activeProfileId'),
            'callable_type' => $activeProfileType,
            'tag_id'        => $this->tagId ?: null,
            'location_id'   => $locationId,
            'from'          => now()->utc(),
            'till'          => $this->till ?: null,
            'is_public'    => $this->isPublic,
        ]);

        CallTranslation::create([
            'call_id' => $call->id,
            'locale'  => App::getLocale(),
            'content' => $this->content ?: null,
        ]);

        $call->searchable();

        $this->showModal = false;
        $this->reset(['content', 'till', 'tagId', 'country', 'division', 'city', 'district', 'isPublic']);

        $this->dispatch('callSaved');

        $this->notification()->success(
            title: __('Saved'),
            description: __('Your Call has been published.')
        );
    }

    public function render()
    {
        $activeProfileType = session('activeProfileType');
        $activeProfileId   = session('activeProfileId');
        $profileName = $activeProfileType
            ? ($activeProfileType::find($activeProfileId)?->name ?? '')
            : '';

        $canCreate = $activeProfileType && $activeProfileId
            ? CallCreditService::profileHasCredits($activeProfileType, (int) $activeProfileId)
            : false;

        // Calculate total spendable balance across all accounts for the active profile
        $spendableBalance = null;
        if ($activeProfileType && $activeProfileId) {
            $profile = $activeProfileType::find($activeProfileId);
            if ($profile) {
                $total = 0;
                foreach ($profile->accounts()->notRemoved()->get() as $account) {
                    $balance = Transaction::where('from_account_id', $account->id)
                        ->orWhere('to_account_id', $account->id)
                        ->selectRaw('SUM(CASE WHEN to_account_id = ? THEN amount ELSE -amount END) as balance', [$account->id])
                        ->value('balance') ?? 0;
                    $total += $balance - $account->limit_min;
                }
                $spendableBalance = $total;
            }
        }

        return view('livewire.calls.create', [
            'profileName'      => $profileName,
            'canCreate'        => $canCreate,
            'spendableBalance' => $spendableBalance,
        ]);
    }
}
