<?php

namespace App\Components;

use App\Interface\AddressOwner;
use App\Models\Address;
use App\Services\HistoryService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Component;

class AddressBook extends Component {
    use AuthorizesRequests;
    public AddressOwner $owner;

    public bool $show = false;

    public bool $editing = false;

    public ?Address $address = null;

    public ?string $display_name = '';
    public string $line_1 = '';
    public ?string $line_2 = '';
    public ?string $line_3 = '';
    public ?string $line_4 = '';
    public ?string $line_5 = '';
    public ?string $line_6 = '';
    public ?string $postcode = '';

    protected array $rules = [
        'display_name' => 'nullable|string|min:1|max:255',
        'line_1' => 'required|string|min:1|max:255',
        'line_2' => 'nullable|string|min:1|max:255',
        'line_3' => 'nullable|string|min:1|max:255',
        'line_4' => 'nullable|string|min:1|max:255',
        'line_5' => 'nullable|string|min:1|max:255',
        'line_6' => 'nullable|string|min:1|max:255',
        'postcode' => [
            'nullable',
            'string',
            'regex:^[A-Za-z]{1,2}\d[A-Za-z\d]? ?\d[A-Za-z]{2}$^',
        ],
    ];

    public function addAddress(HistoryService $historyService) {
        $this->authorize('edit', $this->owner);
        $data = $this->validate($this->rules);

        $clean = [
            'line_1' => isset($data['line_1']) ? trim(ucwords(strtolower($data['line_1']))) : null,
            'line_2' => isset($data['line_2']) ? trim(ucwords(strtolower($data['line_2']))) : null,
            'line_3' => isset($data['line_3']) ? trim(ucwords(strtolower($data['line_3']))) : null,
            'line_4' => isset($data['line_4']) ? trim(ucwords(strtolower($data['line_4']))) : null,
            'line_5' => isset($data['line_5']) ? trim(ucwords(strtolower($data['line_5']))) : null,
            'line_6' => isset($data['line_6']) ? trim(ucwords(strtolower($data['line_6']))) : null,
            'postcode' => isset($data['postcode'])
                ? strtoupper(str_replace(' ', '', $data['postcode']))
                : null,
            'display_name' => isset($data['display_name'])
                ? ucwords(strtolower(trim($data['display_name'])))
                : null,
        ];

        $clean = array_filter($clean, fn($v) => !empty($v));

        $isFirst = $this->owner->addresses()->count() === 0;

        $address = $this->owner->addresses()->create([
            ...$clean,
            'is_current' => $isFirst ? true : false,
        ]);


        $historyService->add($this->owner, 'Address "' . ($clean['line_1'] ?? '') . '" added', [
            'address_id' => $address->id,
            'line_1'     => $clean['line_1'] ?? '',
        ]);

        $this->hideAdd();
    }

    public function hideAdd() {
        $this->reset('line_1', 'line_2', 'line_3', 'line_4', 'line_5', 'line_6', 'postcode', 'display_name');
        $this->show = false;
    }

    public function loadAddress(int $id) {
        $address = $this->owner->addresses()->find($id);

        $this->display_name = $address->display_name;
        $this->line_1 = $address->line_1;
        $this->line_2 = $address->line_2;
        $this->line_3 = $address->line_3;
        $this->line_4 = $address->line_4;
        $this->line_5 = $address->line_5;
        $this->line_6 = $address->line_6;
        $this->postcode = $address->postcode;

        $this->editing = true;
        $this->address = $address;

        $this->showAdd();
    }

    public function showAdd() {
        $this->show = true;
    }

    public function makePrimary(HistoryService $historyService, int $id) {
        $this->authorize('edit', $this->owner);
        $address = $this->owner->addresses()->find($id);

        $this->owner->currentAddress()->update([
            'is_current' => false
        ]);

        $address->update(['is_current' => true]);

        $historyService->add($this->owner, 'Address "' . $address->line_1 . '" set as primary', [
            'address_id' => $address->id,
        ]);
    }

    public function editAddress(HistoryService $historyService, int $id) {
        $this->authorize('edit', $this->owner);
        $data = $this->validate($this->rules);

        $name = $this->owner->addresses()->find($id);

        $old = $name->getAttributes();

        $name->update([
            'display_name' => $data['display_name'],
            'line_1' => $data['line_1'],
            'line_2' => $data['line_2'],
            'line_3' => $data['line_3'],
            'line_4' => $data['line_4'],
            'line_5' => $data['line_5'],
            'line_6' => $data['line_6'],
            'postcode' => $data['postcode'],
        ]);

        $new = $name->fresh()->getAttributes();

        $this->editing = false;
        $this->address = null;

        $historyService->add($this->owner, 'Address "' . ($data['line_1'] ?? '') . '" updated', [
            'address_id' => $id,
        ]);

        $this->hideAdd();
    }

    public function deleteAddress(HistoryService $historyService, int $id)
    {
        $this->authorize('edit', $this->owner);
        $address = $this->owner->addresses()->find($id);

        if (!$address) {
            return;
        }

        $wasCurrent = $address->is_current;

        $address->delete();

        if ($wasCurrent) {
            $newCurrent = $this->owner->addresses()->first();

            if ($newCurrent) {
                $newCurrent->update(['is_current' => true]);
            }
        }

        $historyService->add($this->owner, 'Address "' . $address->line_1 . '" deleted', [
            'address_id' => $id,
        ]);

        $this->hideAdd();
    }


    public function render() {
        return view('components.address-book');
    }
}