<?php

declare(strict_types=1);

namespace App\Services;

use App\Contracts\Repositories\OwnerPaymentAccountRepositoryInterface;
use App\Contracts\Services\OwnerPaymentAccountServiceInterface;
use App\DataTransferObjects\OwnerPaymentAccountData;
use App\Models\OwnerPaymentAccount;

final class OwnerPaymentAccountService implements OwnerPaymentAccountServiceInterface
{
    public function __construct(
        private readonly OwnerPaymentAccountRepositoryInterface $accountRepo,
    ) {}

    public function createAccount(OwnerPaymentAccountData $data): OwnerPaymentAccount
    {
        // If this is the first account, make it primary
        $existingAccounts = $this->accountRepo->getForOwner($data->ownerId);
        $isPrimary = $existingAccounts->isEmpty() || $data->isPrimary;

        // If setting as primary, unset other primary accounts
        if ($isPrimary) {
            $this->accountRepo->unsetPrimaryForOwner($data->ownerId);
        }

        return $this->accountRepo->create([
            'owner_id' => $data->ownerId,
            'type' => $data->type,
            'account_name' => $data->accountName,
            'is_primary' => $isPrimary,
            'details' => $data->details,
            'notes' => $data->notes,
        ]);
    }

    public function updateAccount(int $accountId, OwnerPaymentAccountData $data): OwnerPaymentAccount
    {
        $account = $this->accountRepo->find($accountId);

        if (! $account) {
            throw new \Exception('Account not found');
        }

        // Verify ownership
        if ($account->owner_id !== $data->ownerId) {
            throw new \Exception('Unauthorized');
        }

        // If setting as primary, unset other primary accounts
        if ($data->isPrimary && ! $account->is_primary) {
            $this->accountRepo->unsetPrimaryForOwner($data->ownerId);
        }

        return $this->accountRepo->update($accountId, [
            'type' => $data->type,
            'account_name' => $data->accountName,
            'is_primary' => $data->isPrimary,
            'details' => $data->details,
            'notes' => $data->notes,
        ]);
    }

    public function deleteAccount(int $accountId, int $ownerId): void
    {
        $account = $this->accountRepo->find($accountId);

        if (! $account) {
            throw new \Exception('Account not found');
        }

        // Verify ownership
        if ($account->owner_id !== $ownerId) {
            throw new \Exception('Unauthorized');
        }

        // Prevent deleting the only account
        $ownerAccounts = $this->accountRepo->getForOwner($ownerId);
        if ($ownerAccounts->count() === 1) {
            throw new \Exception('You must have at least one payment account');
        }

        // If deleting primary, set another as primary
        if ($account->is_primary) {
            $newPrimary = $ownerAccounts->where('id', '!=', $accountId)->first();
            if ($newPrimary) {
                $this->accountRepo->update($newPrimary->id, ['is_primary' => true]);
            }
        }

        $this->accountRepo->delete($accountId);
    }

    public function setPrimaryAccount(int $accountId, int $ownerId): void
    {
        $account = $this->accountRepo->find($accountId);

        if (! $account) {
            throw new \Exception('Account not found');
        }

        // Verify ownership
        if ($account->owner_id !== $ownerId) {
            throw new \Exception('Unauthorized');
        }

        // Unset other primary accounts
        $this->accountRepo->unsetPrimaryForOwner($ownerId);

        // Set as primary
        $this->accountRepo->update($accountId, ['is_primary' => true]);
    }
}
