<?php

namespace App\Http\Controllers\Brand;

use App\Http\Controllers\Controller;
use App\Models\AiJob;
use App\Models\Proposal;
use App\Models\ProposalRequest;
use App\Jobs\GenerateProposalJob;
use App\Models\ProposalSection;
use App\Models\ProposalSectionAudit;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;

class AiProposalController extends Controller
{
    /**
     * Show the form for creating a new AI proposal request.
     *
     * @param  int|null  $creatorId
     * @return \Illuminate\Http\Response
     */
    public function create($creatorId = null)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }

        $creator = null;
        if ($creatorId) {
            $creator = User::whereHas('roles', function ($q) {
                $q->where('name', 'creator');
            })->find($creatorId);
        }

        // Get all creators for the dropdown
        $creators = User::whereHas('roles', function ($q) {
            $q->where('name', 'creator');
        })->get();

        return view('brand.proposals.ai-create', compact('creator', 'creators'));
    }

    /**
     * Store a new AI proposal request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }

        // Rate limiting - 5 requests per hour per brand
        $throttleKey = 'ai-proposal-request|' . $brand->id;
        if (RateLimiter::tooManyAttempts($throttleKey, 5)) {
            $retryAfter = RateLimiter::availableIn($throttleKey);
            return response()->json([
                'success' => false,
                'message' => 'Too many requests. Please try again in ' . $retryAfter . ' seconds.',
            ], 429);
        }

        $validated = $request->validate([
            'creator_id' => 'nullable|exists:users,id',
            'campaign_brief' => 'required|string|max:5000',
            'tone' => 'required|string|max:255',
            'budget_range' => 'required|array|size:2',
            'budget_range.*' => 'numeric|min:0',
            'deliverables' => 'required|array',
            'deliverables.*' => 'string|max:255',
        ]);

        // Sanitize PII before sending to AI service
        $sanitizedBrief = $this->sanitizePii($validated['campaign_brief']);

        // Create proposal request
        $proposalRequest = ProposalRequest::create([
            'brand_id' => $brand->id,
            'creator_id' => $validated['creator_id'] ?? null,
            'campaign_brief' => $sanitizedBrief,
            'tone' => $validated['tone'],
            'budget_range' => $validated['budget_range'],
            'deliverables' => $validated['deliverables'],
            'status' => 'pending',
        ]);

        // Enqueue AI job
        $aiJob = $this->enqueueAiJob($brand->id, $validated['creator_id'] ?? null, [
            'campaign_brief' => $sanitizedBrief,
            'tone' => $validated['tone'],
            'budget_range' => $validated['budget_range'],
            'deliverables' => $validated['deliverables'],
            'brand_name' => $brand->name,
            'brand_industry' => $brand->settings['industry'] ?? 'general',
        ]);

        // Link proposal request with AI job
        $proposalRequest->update(['ai_job_id' => $aiJob->id]);

        // Increment rate limiter with 1 hour decay
        RateLimiter::hit($throttleKey, 3600);

        return response()->json([
            'success' => true,
            'message' => 'AI proposal generation started!',
            'job_id' => $aiJob->job_id,
        ]);
    }

    /**
     * Display the generated proposal.
     *
     * @param  string  $jobId
     * @return \Illuminate\Http\Response
     */
    public function show($jobId)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }

        $aiJob = AiJob::where('job_id', $jobId)
            ->where('brand_id', $brand->id)
            ->firstOrFail();

        return view('brand.proposals.ai-show', compact('aiJob'));
    }

    /**
     * Update the generated proposal (save draft or accept).
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  string  $jobId
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $jobId)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }

        $aiJob = AiJob::where('job_id', $jobId)
            ->where('brand_id', $brand->id)
            ->firstOrFail();

        $validated = $request->validate([
            'action' => 'required|in:save_draft,accept,regenerate',
            'title' => 'required_if:action,accept|string|max:255',
            'sections' => 'required_if:action,accept|array',
            'sections.*.title' => 'required_if:action,accept|string|max:255',
            'sections.*.content' => 'required_if:action,accept|string',
            'sections.*.order' => 'required_if:action,accept|integer',
            'price_estimate' => 'required_if:action,accept|numeric|min:0',
        ]);

        switch ($validated['action']) {
            case 'save_draft':
                // Just save the current state as a draft
                return response()->json([
                    'success' => true,
                    'message' => 'Draft saved successfully!',
                ]);

            case 'accept':
                // Create a proposal from the AI-generated content
                $proposal = Proposal::create([
                    'brand_id' => $brand->id,
                    'creator_id' => $aiJob->creator_id,
                    'title' => $validated['title'],
                    'message' => 'AI-generated proposal',
                    'type' => 'Collaboration',
                    'budget' => $validated['price_estimate'],
                    'status' => 'draft',
                    'ai_job_id' => $aiJob->id,
                ]);

                // Create proposal sections
                foreach ($validated['sections'] as $sectionData) {
                    $proposalSection = ProposalSection::create([
                        'proposal_id' => $proposal->id,
                        'title' => $sectionData['title'],
                        'content' => $sectionData['content'],
                        'order' => $sectionData['order'],
                        'is_editable' => true,
                        'edited_by' => Auth::id(),
                        'edited_at' => now(),
                    ]);
                    
                    // Create audit trail entry
                    ProposalSectionAudit::create([
                        'proposal_section_id' => $proposalSection->id,
                        'user_id' => Auth::id(),
                        'action' => 'accept',
                        'old_content' => null,
                        'new_content' => $sectionData['content'],
                    ]);
                }

                // Update AI job status
                $aiJob->update([
                    'status' => 'accepted',
                    'proposal_id' => $proposal->id,
                    'completed_at' => now(),
                ]);

                return response()->json([
                    'success' => true,
                    'message' => 'Proposal accepted and saved!',
                    'redirect' => route('brand.proposals.show', $proposal),
                ]);

            case 'regenerate':
                // Re-queue the AI job
                $this->requeueAiJob($aiJob);
                
                return response()->json([
                    'success' => true,
                    'message' => 'Proposal regeneration started!',
                ]);
        }
    }

    /**
     * Enqueue an AI job for proposal generation.
     *
     * @param  int  $brandId
     * @param  int|null  $creatorId
     * @param  array  $payload
     * @return \App\Models\AiJob
     */
    protected function enqueueAiJob($brandId, $creatorId, $payload)
    {
        $jobId = (string) Str::uuid();

        $aiJob = AiJob::create([
            'job_id' => $jobId,
            'type' => 'generate_proposal',
            'status' => 'queued',
            'brand_id' => $brandId,
            'creator_id' => $creatorId,
            'result_text' => null,
            'result_meta' => null,
            'provider' => null,
        ]);

        // Dispatch the actual job
        GenerateProposalJob::dispatch($aiJob->id, $payload);

        return $aiJob;
    }

    /**
     * Re-queue an AI job for regeneration.
     *
     * @param  \App\Models\AiJob  $aiJob
     * @return void
     */
    protected function requeueAiJob($aiJob)
    {
        $aiJob->update([
            'status' => 'queued',
            'result_text' => null,
            'result_meta' => null,
            'provider' => null,
            'error_message' => null,
            'token_usage' => 0,
            'completed_at' => null,
        ]);

        // Get the original payload from the proposal request
        $proposalRequest = ProposalRequest::where('ai_job_id', $aiJob->id)->first();
        $payload = [
            'campaign_brief' => $proposalRequest->campaign_brief,
            'tone' => $proposalRequest->tone,
            'budget_range' => $proposalRequest->budget_range,
            'deliverables' => $proposalRequest->deliverables,
            'brand_name' => $aiJob->brand->name,
            'brand_industry' => $aiJob->brand->settings['industry'] ?? 'general',
        ];

        // Dispatch the actual job
        GenerateProposalJob::dispatch($aiJob->id, $payload);
    }

    /**
     * Sanitize PII from text before sending to AI service.
     *
     * @param  string  $text
     * @return string
     */
    protected function sanitizePii($text)
    {
        // Remove email addresses
        $text = preg_replace('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/', '[EMAIL]', $text);
        
        // Remove phone numbers (various formats)
        $text = preg_replace('/(\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/', '[PHONE]', $text);
        
        // Remove URLs
        $text = preg_replace('/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/', '[URL]', $text);
        
        // Remove credit card numbers (simple pattern)
        $text = preg_replace('/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/', '[CREDIT CARD]', $text);
        
        // Remove social security numbers
        $text = preg_replace('/\b\d{3}-\d{2}-\d{4}\b/', '[SSN]', $text);
        
        // Remove IP addresses
        $text = preg_replace('/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/', '[IP ADDRESS]', $text);
        
        return $text;
    }
    
    /**
     * Display a list of pending agency proposals for the brand.
     *
     * @return \Illuminate\Http\Response
     */
    public function pendingAgencyProposals()
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }
        
        // Get agency proposals with status 'pending_approval' for this brand
        $proposals = Proposal::where('brand_id', $brand->id)
            ->where('status', 'pending_approval')
            ->whereNotNull('agency_id')
            ->with('agency')
            ->get();
        
        return view('brand.proposals.agency-pending', compact('proposals'));
    }
    
    /**
     * Display a specific agency proposal.
     *
     * @param  \App\Models\Proposal  $proposal
     * @return \Illuminate\Http\Response
     */
    public function showAgencyProposal(Proposal $proposal)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->view('errors.brand-not-found', [], 404);
        }
        
        // Check if the proposal belongs to this brand and is agency-generated
        if ($proposal->brand_id !== $brand->id || !$proposal->agency_id) {
            return response()->view('errors.403', [], 403);
        }
        
        // Get the AI job associated with this proposal
        $aiJob = $proposal->aiJob;
        
        return view('brand.proposals.agency-show', compact('proposal', 'aiJob'));
    }
    
    /**
     * Approve an agency-generated proposal.
     *
     * @param  \App\Models\Proposal  $proposal
     * @return \Illuminate\Http\Response
     */
    public function approveAgencyProposal(Proposal $proposal)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->json(['success' => false, 'message' => 'Brand not found'], 404);
        }
        
        // Check if the proposal belongs to this brand and is agency-generated
        if ($proposal->brand_id !== $brand->id || !$proposal->agency_id) {
            return response()->json(['success' => false, 'message' => 'Unauthorized'], 403);
        }
        
        // Check if the proposal is in pending_approval status
        if ($proposal->status !== 'pending_approval') {
            return response()->json(['success' => false, 'message' => 'Proposal is not pending approval'], 400);
        }
        
        // Update the proposal status to 'sent'
        $proposal->update(['status' => 'sent']);
        
        // Log the approval action
        \App\Models\AuditLog::create([
            'actor_id' => Auth::id(),
            'action' => 'approve_agency_proposal',
            'target_type' => 'Proposal',
            'target_id' => $proposal->id,
            'meta' => [
                'agency_id' => $proposal->agency_id,
                'previous_status' => 'pending_approval',
                'new_status' => 'sent',
            ],
        ]);
        
        return response()->json([
            'success' => true,
            'message' => 'Proposal approved successfully!',
            'redirect' => route('brand.proposals.index'),
        ]);
    }
    
    /**
     * Reject an agency-generated proposal.
     *
     * @param  \App\Models\Proposal  $proposal
     * @return \Illuminate\Http\Response
     */
    public function rejectAgencyProposal(Proposal $proposal)
    {
        $brand = Auth::user()->brand;
        if (!$brand) {
            return response()->json(['success' => false, 'message' => 'Brand not found'], 404);
        }
        
        // Check if the proposal belongs to this brand and is agency-generated
        if ($proposal->brand_id !== $brand->id || !$proposal->agency_id) {
            return response()->json(['success' => false, 'message' => 'Unauthorized'], 403);
        }
        
        // Check if the proposal is in pending_approval status
        if ($proposal->status !== 'pending_approval') {
            return response()->json(['success' => false, 'message' => 'Proposal is not pending approval'], 400);
        }
        
        // Update the proposal status to 'rejected'
        $proposal->update(['status' => 'rejected']);
        
        // Log the rejection action
        \App\Models\AuditLog::create([
            'actor_id' => Auth::id(),
            'action' => 'reject_agency_proposal',
            'target_type' => 'Proposal',
            'target_id' => $proposal->id,
            'meta' => [
                'agency_id' => $proposal->agency_id,
                'previous_status' => 'pending_approval',
                'new_status' => 'rejected',
            ],
        ]);
        
        return response()->json([
            'success' => true,
            'message' => 'Proposal rejected successfully!',
            'redirect' => route('brand.proposals.index'),
        ]);
    }
}