<?php

namespace App\Models;

use App\Campaigns\Platforms\PlatformRules;
use App\DTOs\LandingPageAnalysis;
use Database\Factories\BriefFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;

/**
 * What the user wants to advertise, independent of where it runs.
 *
 * One per conversation. A campaign belongs to a brief and holds only what its
 * own platform needs: the ad account, the objective in that platform's
 * vocabulary, the Page, the pixel. Everything the buyer would give the same
 * answer to twice lives here instead, which is what stops a second platform
 * re-asking the whole flow.
 *
 * Deliberately holds the plain answer rather than any platform's enum. The
 * outcome is "sales", not OUTCOME_SALES and not a Google conversion goal;
 * translating it is the platform's job, in {@see PlatformRules}.
 */
#[Fillable([
    'user_id', 'conversation_id', 'landing_url', 'promoting', 'outcome',
    'locations', 'budget', 'budget_mode', 'currency', 'starts_at', 'ends_at',
    'page_analysis',
])]
class Brief extends Model
{
    /** @use HasFactory<BriefFactory> */
    use HasFactory;

    protected function casts(): array
    {
        return [
            'locations' => 'array',
            'page_analysis' => 'array',
            'budget' => 'decimal:2',
            'starts_at' => 'datetime',
            'ends_at' => 'datetime',
        ];
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /** Every platform's campaign built from this brief. */
    public function campaigns(): HasMany
    {
        return $this->hasMany(Campaign::class);
    }

    public function targetingSet(): HasOne
    {
        return $this->hasOne(TargetingSet::class);
    }

    /** @return list<string> the platforms this brief has already produced a campaign for */
    public function platforms(): array
    {
        return $this->campaigns()->pluck('platform')->filter()->unique()->values()->all();
    }

    /**
     * Whether the money still has to be divided between platforms.
     *
     * True only while the division is genuinely outstanding: a total to share,
     * more than one platform sharing it, and at least one of them holding no
     * share of its own. A campaign with no budget of its own falls back to the
     * brief's total through {@see ResolvesFromBrief}, so leaving it unsplit
     * means every platform spends the whole amount.
     *
     * This used to return true whenever there was more than one platform, which
     * answers a different question and stayed true long after the money had
     * been divided.
     */
    public function needsBudgetSplit(): bool
    {
        if ((float) $this->budget <= 0 || count($this->platforms()) < 2) {
            return false;
        }

        return $this->campaigns()->whereNull('budget')->exists();
    }

    /**
     * What the landing page told us, as the object the analyser returns.
     *
     * Stored as json so the flow can keep suggesting from the page without
     * fetching it again on every turn.
     */
    public function pageAnalysis(): ?LandingPageAnalysis
    {
        $stored = $this->page_analysis;

        if (! is_array($stored) || blank($stored['url'] ?? null)) {
            return null;
        }

        return new LandingPageAnalysis(
            url: (string) $stored['url'],
            title: (string) ($stored['title'] ?? ''),
            description: (string) ($stored['description'] ?? ''),
            headings: array_values((array) ($stored['headings'] ?? [])),
            text: (string) ($stored['text'] ?? ''),
            keywords: array_values((array) ($stored['keywords'] ?? [])),
        );
    }

    public function rememberPageAnalysis(LandingPageAnalysis $analysis): void
    {
        $this->update([
            'landing_url' => $analysis->url,
            'page_analysis' => [
                'url' => $analysis->url,
                'title' => $analysis->title,
                'description' => $analysis->description,
                'headings' => $analysis->headings,
                'text' => $analysis->text,
                'keywords' => $analysis->keywords,
            ],
        ]);
    }
}
