<?php

namespace App\Agent\Tools\Campaign;

use App\Agent\Choices;
use App\Agent\Tools\Campaign\Concerns\ActsOnFocusedCampaign;
use App\Agent\Workspace;
use App\Models\ArtifactFieldSource;
use App\Models\TikTokConnection;
use App\Services\TikTokService;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;
use RuntimeException;
use Stringable;

class ChooseTikTokIdentity implements Tool
{
    use ActsOnFocusedCampaign;

    public function __construct(
        private readonly Workspace $workspace,
        private readonly Choices $choices,
        private readonly TikTokService $tiktok,
    ) {}

    public function description(): Stringable|string
    {
        return 'List authorized TikTok identities and select one for the campaign. '
            .'Call without identity to offer choices or auto-select the only identity.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'identity' => $schema->string()
                ->description('Selected identity value in identity_type|identity_id form.'),
        ];
    }

    public function handle(Request $request): Stringable|string
    {
        if (! $campaign = $this->focused()) {
            return $this->noCampaign();
        }

        $connection = TikTokConnection::query()->where('user_id', auth()->id())->first();
        if ($connection === null || blank($connection->access_token) || blank($connection->advertiser_id)) {
            return $this->json(['ok' => false, 'error' => 'Connect TikTok Ads and select an advertiser first.']);
        }

        try {
            $identities = $this->tiktok->identities($connection);
        } catch (RuntimeException $exception) {
            return $this->json(['ok' => false, 'error' => $exception->getMessage()]);
        }

        $selected = trim((string) ($request->all()['identity'] ?? ''));
        if ($selected === '') {
            if (count($identities) === 1) {
                $identity = $identities[0];
            } elseif ($identities === []) {
                return $this->json(['ok' => false, 'error' => 'No TikTok identities are authorized for this advertiser.']);
            } else {
                $this->choices->offer(
                    field: 'tiktok_identity',
                    question: 'Which TikTok identity should the ad use?',
                    options: array_map(fn (array $identity): array => [
                        'value' => $identity['identity_type'].'|'.$identity['identity_id'],
                        'label' => $identity['identity_name'],
                        'hint' => $identity['identity_type'],
                        'sends' => 'Use TikTok identity '.$identity['identity_name'].'.',
                    ], $identities),
                );

                return $this->json(['ok' => true, 'selection_required' => true]);
            }
        } else {
            [$identityType, $identityId] = array_pad(explode('|', $selected, 2), 2, '');
            $identity = collect($identities)->first(fn (array $candidate): bool =>
                $candidate['identity_type'] === $identityType && $candidate['identity_id'] === $identityId
            );

            // Older choice cards sent the visible identity name rather than
            // its canonical value. Resolve that exact label for compatibility,
            // then persist the real type and id below.
            $identity ??= collect($identities)->first(fn (array $candidate): bool =>
                $candidate['identity_name'] === $selected
            );

            $identity ??= collect($identities)->first(fn (array $candidate): bool =>
                $candidate['identity_id'] === $selected
            );

            if (! is_array($identity)) {
                return $this->json(['ok' => false, 'error' => 'Choose a TikTok identity returned for this advertiser.']);
            }
        }

        $connection->forceFill([
            'identity_id' => $identity['identity_id'],
            'identity_authorized_bc_id' => $identity['identity_authorized_bc_id'] ?? null,
            'identity_type' => $identity['identity_type'],
            'identity_name' => $identity['identity_name'],
            'identities' => $identities,
            'tiktok_posts' => null,
            'tiktok_item_id' => null,
        ])->save();

        if ($identity['identity_type'] === 'BC_AUTH_TT') {
            $posts = $this->tiktok->identityPosts($connection);
            $connection->forceFill([
                'tiktok_posts' => $posts,
                'tiktok_item_id' => count($posts) === 1 ? $posts[0]['item_id'] : null,
            ])->save();
        }

        $campaign->update(['meta' => [
            ...(array) $campaign->meta,
            'tiktok_identity_id' => $identity['identity_id'],
            'tiktok_identity_type' => $identity['identity_type'],
            'tiktok_identity_name' => $identity['identity_name'],
        ]]);
        $this->workspace->recordSource($campaign, 'tiktok_identity', ArtifactFieldSource::PLATFORM_RETURNED);

        return $this->json([
            'ok' => true,
            'identity_id' => $identity['identity_id'],
            'identity_type' => $identity['identity_type'],
            'identity_name' => $identity['identity_name'],
            'auto_selected' => $selected === '',
        ]);
    }
}