<?php

namespace App\Mcp\Tools\GoogleAds;

use App\Models\GoogleAdsCampaign;
use App\Models\GoogleAdsConnection;
use App\Services\GoogleAdsService;
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('Create a paused live Google Ads Search campaign with an ad group, keywords, and responsive search ad for the authenticated user\'s selected child account.')]
class CreateCampaign extends Tool
{
    public function __construct(private readonly GoogleAdsService $googleAds) {}

    public function schema(JsonSchema $schema): array
    {
        return [
            'name' => $schema->string()->description('Campaign name')->required(),
            'campaign_type' => $schema->string()->description('Campaign type: Search, Display, Video-led Performance Max, or Performance Max')->required(),
            'conversion_goal' => $schema->string()->description('Primary conversion goal or Google Ads conversion action')->required(),
            'bidding_strategy' => $schema->string()->description('Bidding strategy: max_conversions, max_conversion_value, or max_clicks')->required(),
            'daily_budget' => $schema->number()->description('Daily budget in the account currency')->required(),
            'ad_group_name' => $schema->string()->description('Ad group name')->required(),
            'locations' => $schema->string()->description('Locations to target')->required(),
            'languages' => $schema->string()->description('Languages to target')->required(),
            'schedule' => $schema->string()->description('Ad schedule, if restricted'),
            'audience_signals' => $schema->string()->description('Audience signals or demographics'),
            'networks' => $schema->string()->description('Selected networks, such as Google Search or Search Partners')->required(),
            'business_name' => $schema->string()->description('Advertiser name for Display campaigns'),
            'long_headline' => $schema->string()->description('Long headline for Display campaigns, up to 90 characters'),
            'call_to_action_text' => $schema->string()->description('Optional Display call to action'),
            'marketing_image_assets' => $schema->string()->description('Comma-separated Google Ads image asset resource names for Display'),
            'square_marketing_image_assets' => $schema->string()->description('Comma-separated square Google Ads image asset resource names for Display'),
            'logo_image_assets' => $schema->string()->description('Optional comma-separated Google Ads logo asset resource names for Display'),
            'cpm_bid' => $schema->number()->description('Display CPM bid in account currency'),
            'asset_group_name' => $schema->string()->description('Performance Max asset group name'),
            'long_headlines' => $schema->string()->description('Comma-separated Performance Max long-headline asset resource names'),
            'youtube_video_assets' => $schema->string()->description('Optional comma-separated YouTube video asset resource names for Performance Max'),
            'headlines' => $schema->array()->description('Search/Display text headlines, or three Google Ads text-asset resource names for Performance Max')->required(),
            'descriptions' => $schema->array()->description('Search/Display text descriptions, or two Google Ads text-asset resource names for Performance Max')->required(),
            'final_url' => $schema->string()->description('Landing page URL')->required(),
            'keywords' => $schema->string()->description('Comma-separated keywords')->required(),
        ];
    }

    public function handle(Request $request): Response
    {
        $user = $request->user();
        if ($user === null) {
            return Response::error('Authentication is required.');
        }

        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'campaign_type' => ['required', 'string', 'in:Search,search,Display,display,Video,video,Performance Max,performance_max'],
            'conversion_goal' => ['required', 'string', 'max:255'],
            'bidding_strategy' => ['required', 'string', 'in:max_conversions,max_conversion_value,max_clicks'],
            'daily_budget' => ['required', 'numeric', 'min:0.01'],
            'ad_group_name' => ['required', 'string', 'max:255'],
            'locations' => ['required', 'string', 'max:1000'],
            'languages' => ['required', 'string', 'max:500'],
            'schedule' => ['nullable', 'string', 'max:500'],
            'audience_signals' => ['nullable', 'string', 'max:1000'],
            'networks' => ['required', 'string', 'max:500'],
            'business_name' => ['nullable', 'string', 'max:25'],
            'long_headline' => ['nullable', 'string', 'max:90'],
            'call_to_action_text' => ['nullable', 'string', 'max:30'],
            'marketing_image_assets' => ['nullable', 'string', 'max:2000'],
            'square_marketing_image_assets' => ['nullable', 'string', 'max:2000'],
            'logo_image_assets' => ['nullable', 'string', 'max:2000'],
            'cpm_bid' => ['nullable', 'numeric', 'min:0.01'],
            'asset_group_name' => ['nullable', 'string', 'max:128'],
            'long_headlines' => ['nullable', 'string', 'max:2000'],
            'youtube_video_assets' => ['nullable', 'string', 'max:2000'],
            'headlines' => ['required', 'array', 'size:3'],
            'headlines.*' => ['required', 'string'],
            'descriptions' => ['required', 'array', 'size:2'],
            'descriptions.*' => ['required', 'string'],
            'final_url' => ['required', 'url', 'max:2048'],
            'keywords' => ['required', 'string', 'max:1000'],
        ]);
        if (strtolower($data['campaign_type']) === 'display') {
            foreach (['business_name', 'long_headline', 'marketing_image_assets', 'square_marketing_image_assets'] as $field) {
                if (blank($data[$field] ?? null)) {
                    return Response::error("{$field} is required for Display campaigns.");
                }
            }

            $data['marketing_image_assets'] = array_values(array_filter(array_map('trim', explode(',', $data['marketing_image_assets']))));
            $data['square_marketing_image_assets'] = array_values(array_filter(array_map('trim', explode(',', $data['square_marketing_image_assets']))));
            $data['logo_image_assets'] = array_values(array_filter(array_map('trim', explode(',', (string) ($data['logo_image_assets'] ?? '')))));
            if ($data['marketing_image_assets'] === [] || $data['square_marketing_image_assets'] === []) {
                return Response::error('Display campaigns require both landscape and square image asset resource names.');
            }
        }
        if (in_array(strtolower($data['campaign_type']), ['search', 'display'], true)) {
            if (collect($data['headlines'])->contains(fn (string $headline): bool => mb_strlen($headline) > 30)) {
                return Response::error('Headlines must be 30 characters or fewer for Search and Display campaigns.');
            }
            if (collect($data['descriptions'])->contains(fn (string $description): bool => mb_strlen($description) > 90)) {
                return Response::error('Descriptions must be 90 characters or fewer for Search and Display campaigns.');
            }
        }
        if (strtolower($data['campaign_type']) === 'performance max') {
            $data['campaign_type'] = 'performance_max';
        }
        if (in_array(strtolower($data['campaign_type']), ['performance max', 'performance_max', 'video'], true)) {
            if (strtolower($data['campaign_type']) === 'performance max') {
                $data['campaign_type'] = 'performance_max';
            }
            foreach (['asset_group_name', 'long_headlines', 'marketing_image_assets', 'square_marketing_image_assets'] as $field) {
                if (blank($data[$field] ?? null)) {
                    return Response::error("{$field} is required for Performance Max campaigns.");
                }
            }
            $data['long_headlines'] = array_values(array_filter(array_map('trim', explode(',', $data['long_headlines']))));
            $data['marketing_image_assets'] = array_values(array_filter(array_map('trim', explode(',', (string) ($data['marketing_image_assets'] ?? '')))));
            $data['square_marketing_image_assets'] = array_values(array_filter(array_map('trim', explode(',', (string) ($data['square_marketing_image_assets'] ?? '')))));
            $data['logo_image_assets'] = array_values(array_filter(array_map('trim', explode(',', (string) ($data['logo_image_assets'] ?? '')))));
            $data['youtube_video_assets'] = array_values(array_filter(array_map('trim', explode(',', (string) ($data['youtube_video_assets'] ?? '')))));
            if (count($data['headlines']) < 3 || count($data['long_headlines']) < 1 || count($data['descriptions']) < 2) {
                return Response::error('Performance Max requires at least three headlines, one long headline, and two descriptions.');
            }
        }
        if (in_array(strtolower($data['campaign_type']), ['video'], true)) {
            foreach (['asset_group_name', 'long_headlines', 'marketing_image_assets', 'square_marketing_image_assets', 'youtube_video_assets'] as $field) {
                if (blank($data[$field] ?? null)) {
                    return Response::error("{$field} is required for Video-led Performance Max campaigns.");
                }
            }
        }
        $connection = GoogleAdsConnection::query()->where('user_id', $user->getAuthIdentifier())->first();
        if ($connection === null || blank($connection->customer_id)) {
            return Response::error('Select a child Google Ads account first.');
        }

        try {
            $ids = $this->googleAds->createPausedCampaign($connection, $data);
            $campaign = GoogleAdsCampaign::create([
                'user_id' => $user->getAuthIdentifier(),
                'google_ads_connection_id' => $connection->id,
                'google_campaign_id' => $ids['campaign_id'],
                'google_campaign_budget_id' => $ids['budget_id'],
                'google_ad_group_id' => $ids['ad_group_id'],
                'google_ad_id' => $ids['ad_id'],
                'google_asset_group_id' => $ids['asset_group_id'] ?? null,
                'name' => $data['name'],
                'status' => 'paused',
                'daily_budget' => $data['daily_budget'],
                'ad_group_name' => $data['ad_group_name'],
                'final_url' => $data['final_url'],
                'notes' => json_encode([
                    'conversion_goal' => $data['conversion_goal'],
                    'campaign_type' => $data['campaign_type'],
                    'bidding_strategy' => $data['bidding_strategy'],
                    'asset_group_name' => $data['asset_group_name'] ?? null,
                    'business_name' => $data['business_name'] ?? null,
                    'long_headline' => $data['long_headline'] ?? null,
                    'long_headlines' => $data['long_headlines'] ?? null,
                    'call_to_action_text' => $data['call_to_action_text'] ?? null,
                    'marketing_image_assets' => $data['marketing_image_assets'] ?? null,
                    'square_marketing_image_assets' => $data['square_marketing_image_assets'] ?? null,
                    'logo_image_assets' => $data['logo_image_assets'] ?? null,
                    'youtube_video_assets' => $data['youtube_video_assets'] ?? null,
                    'locations' => $data['locations'],
                    'languages' => $data['languages'],
                    'schedule' => $data['schedule'] ?? null,
                    'audience_signals' => $data['audience_signals'] ?? null,
                    'networks' => $data['networks'],
                    'headlines' => $data['headlines'],
                    'descriptions' => $data['descriptions'],
                    'keywords' => $data['keywords'],
                ], JSON_UNESCAPED_SLASHES),
            ]);
        } catch (Throwable $exception) {
            report($exception);

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

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