<?php

namespace App\Mcp\Tools\TikTok;

use App\Agent\Choices;
use App\Models\TikTokConnection;
use App\Services\TikTokService;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Mcp\Request;
use Laravel\Mcp\Response;
use Laravel\Mcp\Server\Attributes\Description;
use Laravel\Mcp\Server\Tool;
use Throwable;

#[Description('List TikTok advertisers available to the authenticated user. Use this before TikTok campaign operations.')]
class ListAdvertisers extends Tool
{
    public function __construct(
        private readonly TikTokService $tiktok,
        private readonly Choices $choices,
    ) {}

    public function schema(JsonSchema $schema): array
    {
        return [];
    }

    public function handle(Request $request): Response
    {
        $connection = TikTokConnection::query()->where('user_id', $request->user()?->getAuthIdentifier())->first();
        if ($connection === null || blank($connection->access_token)) {
            return Response::error('Connect TikTok Ads first.');
        }

        try {
            $advertisers = $this->tiktok->advertisers($connection);
        } catch (Throwable $exception) {
            report($exception);

            return Response::error($exception->getMessage());
        }

        $selectedAdvertiser = collect($advertisers)->first(fn (array $advertiser): bool => filled($connection->advertiser_name)
            && (string) ($advertiser['advertiser_id'] ?? '') === (string) $connection->advertiser_id
        );

        if ($selectedAdvertiser === null && filled(config('services.tiktok.advertiser_id'))) {
            $configuredAdvertiserId = (string) config('services.tiktok.advertiser_id');
            $selectedAdvertiser = collect($advertisers)->first(fn (array $advertiser): bool => (string) ($advertiser['advertiser_id'] ?? '') === $configuredAdvertiserId
            );
        }

        $connection->forceFill(['advertisers' => $advertisers])->save();

        if ($selectedAdvertiser !== null) {
            $attributes = [
                'advertiser_id' => $selectedAdvertiser['advertiser_id'],
                'advertiser_name' => $selectedAdvertiser['advertiser_name'],
            ];
            if ((string) $connection->advertiser_id !== (string) $selectedAdvertiser['advertiser_id']) {
                $attributes += $this->emptyIdentityAttributes();
            }
            $connection->forceFill($attributes)->save();
            $this->offerAdvertiserChoices($advertisers, (string) $selectedAdvertiser['advertiser_id']);

            return Response::json([
                'ok' => true,
                'advertisers' => $advertisers,
                'selected_advertiser' => [...$selectedAdvertiser, 'verified' => true],
                'selection_required' => count($advertisers) > 1,
            ]);
        }

        if ($advertisers === [] && filled(config('services.tiktok.advertiser_id'))) {
            $configuredAdvertiserId = (string) config('services.tiktok.advertiser_id');
            $attributes = [
                'advertiser_id' => $configuredAdvertiserId,
                'advertiser_name' => 'Configured TikTok advertiser',
            ];
            if ((string) $connection->advertiser_id !== $configuredAdvertiserId) {
                $attributes += $this->emptyIdentityAttributes();
            }
            $connection->forceFill($attributes)->save();

            return Response::json([
                'ok' => true,
                'advertisers' => [],
                'selected_advertiser' => [
                    'advertiser_id' => $configuredAdvertiserId,
                    'advertiser_name' => 'Configured TikTok advertiser',
                    'verified' => false,
                ],
            ]);
        }

        $connection->forceFill([
            'advertiser_id' => null,
            'advertiser_name' => null,
            ...$this->emptyIdentityAttributes(),
        ])->save();
        $this->offerAdvertiserChoices($advertisers, null);

        return Response::json(['ok' => true, 'advertisers' => $advertisers]);
    }

    /** @param list<array{advertiser_id: string, advertiser_name: string}> $advertisers */
    private function offerAdvertiserChoices(array $advertisers, ?string $selectedAdvertiserId): void
    {
        if (count($advertisers) < 2) {
            return;
        }

        $this->choices->offer(
            field: 'tiktok_advertiser_id',
            question: 'Which TikTok advertiser should we use?',
            options: array_map(fn (array $advertiser): array => [
                'value' => $advertiser['advertiser_id'],
                'label' => $advertiser['advertiser_name'],
                'hint' => (string) $advertiser['advertiser_id'].((string) $advertiser['advertiser_id'] === $selectedAdvertiserId ? ' - currently selected' : ''),
                'sends' => 'Select TikTok advertiser '.$advertiser['advertiser_id'],
            ], $advertisers),
        );
    }

    /** @return array{identities: null, identity_id: null, identity_authorized_bc_id: null, identity_type: null, identity_name: null, tiktok_posts: null, tiktok_item_id: null} */
    private function emptyIdentityAttributes(): array
    {
        return ['identities' => null, 'identity_id' => null, 'identity_authorized_bc_id' => null, 'identity_type' => null, 'identity_name' => null, 'tiktok_posts' => null, 'tiktok_item_id' => null];
    }
}
