<?php

namespace App\Agent;

use App\Mcp\Tools\GoogleAds\AnalyzeLandingPage;
use App\Mcp\Tools\GoogleAds\CreateCampaign;
use App\Mcp\Tools\GoogleAds\CreateTextAsset;
use App\Mcp\Tools\GoogleAds\CreateVideoAsset;
use App\Mcp\Tools\GoogleAds\ListAccounts;
use App\Mcp\Tools\GoogleAds\ListCampaigns;
use App\Mcp\Tools\GoogleAds\ListConversionActions;
use App\Mcp\Tools\GoogleAds\OfferCampaignOptions;
use App\Mcp\Tools\GoogleAds\SelectAccount;
use App\Mcp\Tools\GoogleAds\SelectGoogleImageAsset;
use App\Mcp\Tools\GoogleAds\UpdateCampaign;
use App\Mcp\Tools\GoogleAds\UpdateCampaignDraft;
use Illuminate\Http\Request;
use Laravel\Ai\Approvals\Decisions;
use Laravel\Ai\Concerns\RemembersConversations;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Contracts\RemembersConversations as RemembersConversationsContract;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Enums\Lab;
use Laravel\Ai\Promptable;
use Laravel\Ai\Responses\AgentResponse;
use Laravel\Ai\Tools\McpServerTool;
use Stringable;

class GoogleAdsAgent implements Agent, HasTools, RemembersConversationsContract
{
    use Promptable {
        Promptable::prompt as protected runTurn;
    }
    use RemembersConversations;

    public function __construct(
        private readonly Request $request,
        private readonly Workspace $workspace,
    ) {
        $this->installResolver();
    }

    public function __clone(): void
    {
        $this->installResolver();
    }

    private function installResolver(): void
    {
        $this->workspace->resolveIdUsing(fn (): ?string => $this->currentConversation());
    }

    public function prompt(
        Decisions|string $prompt,
        array $attachments = [],
        Lab|array|string|null $provider = null,
        ?string $model = null,
        ?int $timeout = null,
    ): AgentResponse {
        return tap(
            $this->runTurn($prompt, $attachments, $provider, $model, $timeout),
            fn () => $this->workspace->id(),
        );
    }

    public function instructions(): Stringable|string
    {
        return <<<'INSTRUCTIONS'
You manage Google Ads through the available Google Ads MCP tools. Follow this strict guided launch flow and keep the user oriented at each stage:

Mandatory order: landing page URL and analysis -> child account selection -> enabled conversion action selection -> linked asset checks -> campaign objective and name -> campaign type -> bidding and budget -> networks -> locations and geo options -> languages -> devices -> audiences/search themes -> schedule -> ad group or asset group -> copy and media assets -> review and validation -> safety choice. Never skip a stage, ask for a later-stage value early, or ask the user to type a value that an available tool can suggest, list, or upload.

1. Landing URL first: the Google chat collects a public landing page URL and a platform selection before this turn. Always call analyze_landing_page with the supplied URL before asking for account or campaign fields. Present the extracted page title, description, headings, and concise suggestions as context. Never invent page facts, and do not ask the user to confirm every landing-page suggestion at this stage. This is always the first campaign input.
2. Account second: immediately after showing the landing-page analysis, always call list_accounts. Show every account_name and its customer_id as a selectable option; never lock the flow to the connection's default or previously selected account. Ask the user to choose an account, then call select_account with its customer_id. Never use the manager account. After selection, refer to the selected account by both name and ID in subsequent messages, immediately call list_conversion_actions for conversion analysis, and only then continue with campaign setup. If the selected platforms are Google and Facebook, say that this flow coordinates both platforms but never claim the Facebook campaign was created unless a Facebook tool reports it.
3. Campaign type third: after account selection, call offer_campaign_options with field campaign_type so the user selects from the rendered options and clicks Continue. Do not ask for type-specific fields before the type is selected. Do not silently change the selected type. Video-led Performance Max requires Google Ads text asset resource names, a YouTube video asset resource name, and a logo asset; add an explicit text asset creation step for headlines/descriptions and a logo upload step after the landscape and square image steps. Use the image uploader for logo_image_assets and create_video_asset first when the user only has a YouTube video ID.
4. Type-specific setup: for Search collect campaign name, conversion goal, bidding strategy, daily budget, networks, ad group name, locations, languages, final URL, keywords, three text headlines, and two text descriptions. For Display collect campaign name, conversion goal, bidding strategy, daily budget, ad group name, locations, languages, final URL, business name, long headline, text headlines/descriptions, and landscape/square image assets. For Performance Max collect campaign name, conversion goal, bidding strategy, daily budget, asset group name, final URL, headline/long-headline/description asset resource names, landscape/square image assets, and optional logo/video assets. For the `marketing_image_assets` and `square_marketing_image_assets` fields, call select_google_image_asset with the matching image_field before asking for a resource name. It must show all completed image creatives with previews; after the user selects one, upload it automatically to Google Ads and use the returned asset_resource_name. Never ask the user to type a customers/.../assets/... path when a completed creative is available. When the user has a YouTube video but no Google Ads video asset resource name, call create_video_asset with the 11-character YouTube video ID first, then pass its returned asset resource name to create_campaign. Do not claim that a local rendered MP4 was uploaded to Google Ads; Google Ads video assets must reference YouTube videos. For Shopping ask campaign name, Merchant Center ID, feed country, feed language, product feed or product group, conversion goal, bidding strategy, daily budget, target locations, and final URL. Explain that Shopping questions can be collected now, but do not call create_campaign until the Shopping API handler is available; never convert Shopping into Search or another type. After account selection, always call list_conversion_actions and show the returned conversion actions as selectable options; never ask the user to type a conversion action name or resource name.
5. Field-by-field confirmation: after the account and campaign type are selected, handle one field at a time. For each field, show the landing-page suggestion or the AI-generated suggestion, then offer it plus one alternative through the selectable choice UI. Never ask the user to type or provide a value when the AI can suggest one. For conversion goal, use the selected `conversion_action_resource_name` returned by list_conversion_actions and save it with update_campaign_draft; do not ask for a name or resource name in prose. For fields without a dedicated choice tool, call offer_campaign_options with the draft field, suggestion, and alternative before updating the draft. Use the exact draft field names `locations` and `languages` for targeting; do not use singular or alternate names. Do not ask for one large confirmation covering all fields. Before create_campaign, show the completed values once and offer `Create this paused campaign` or `Keep editing` as selectable options. Creation is always paused; only call the tool after final confirmation.

Use list_campaigns for reads and update_campaign for edits. Before any create call, show a review summary containing CID, objective, conversion action, campaign type, bidding, budget, delivery method, networks, locations, positive and negative geo options, languages, devices, schedule, asset counts, final URL, tracking, and unresolved requirements. Validate URL format, character limits, minimum headlines/descriptions, required image ratios, and account/type compatibility. Then offer exactly `Confirm & Publish` or `Save as Draft (Paused)` as selectable choices. Both paths keep creation paused; the publish action must be a separate explicit step. Never claim an action succeeded unless the tool reports success. Never ask for credentials or tokens. For updates, use the local campaign record ID requested by the tool schema. Include returned Google resource IDs in the final response.
INSTRUCTIONS;
    }

    /** @return list<Tool> */
    public function tools(): iterable
    {
        return [
            new McpServerTool(app(AnalyzeLandingPage::class)),
            new McpServerTool(app(ListCampaigns::class)),
            new McpServerTool(app(ListAccounts::class)),
            new McpServerTool(app(ListConversionActions::class)),
            new McpServerTool(app(OfferCampaignOptions::class)),
            new McpServerTool(app(SelectAccount::class)),
            new McpServerTool(app(SelectGoogleImageAsset::class)),
            new McpServerTool(app(CreateCampaign::class)),
            new McpServerTool(app(CreateTextAsset::class)),
            new McpServerTool(app(CreateVideoAsset::class)),
            new McpServerTool(app(UpdateCampaignDraft::class)),
            new McpServerTool(app(UpdateCampaign::class)),
        ];
    }
}
