<?php
namespace App\Http\Controllers;
use App\Models\Campaign;
use App\Models\CampaignTarget;
use App\Models\Contact;
use App\Models\Deal;
use App\Models\IntegrationSyncLog;
use App\Models\Lead;
use App\Models\User;
use App\Models\AuditLog;
use App\Services\CrmIntegrationService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class CampaignAudienceController extends Controller
{
    public function index(Campaign $campaign): View
    {
        $this->authorizeCampaign($campaign);
        $campaign->load(['targets.target']);
        $logs=IntegrationSyncLog::where('payload->campaign_id',$campaign->id)->latest()->limit(100)->get();
        $total=$campaign->targets->count(); $responded=$campaign->targets->whereNotNull('response_status')->count();
        $converted=$campaign->targets->where('converted',true)->count();
        $analytics=['total'=>$total,'sent'=>$campaign->targets->whereNotNull('sent_at')->count(),'responded'=>$responded,
            'converted'=>$converted,'response_rate'=>$total?round($responded/$total*100,1):0,
            'conversion_rate'=>$total?round($converted/$total*100,1):0,
            'value'=>$campaign->targets->sum('conversion_value')];
        $owners=User::where('business_id',$campaign->business_id)->orderBy('name')->get(['id','name']);
        return view('campaigns.audience',compact('campaign','logs','analytics','owners'));
    }

    public function add(Request $request, Campaign $campaign): RedirectResponse
    {
        $this->authorizeCampaign($campaign);
        $data=$request->validate(['type'=>'required|in:lead,contact,customer','ids'=>'required|array|min:1','ids.*'=>'integer']);
        $model=$data['type']==='lead'?Lead::class:Contact::class;
        foreach(array_unique($data['ids']) as $id){
            $target=$model::findOrFail($id); abort_unless($target->business_id===$campaign->business_id,403);
            if($data['type']==='customer') abort_unless(strtolower((string)$target->type)==='customer',422);
            CampaignTarget::withTrashed()->updateOrCreate(
                ['campaign_id'=>$campaign->id,'target_type'=>$model,'target_id'=>$target->id],
                ['business_id'=>$campaign->business_id,'deleted_at'=>null]
            );
        }
        return back()->with('success','Campaign audience updated.');
    }

    public function remove(Campaign $campaign, CampaignTarget $target): RedirectResponse
    {
        $this->authorizeCampaign($campaign); abort_unless($target->campaign_id===$campaign->id,404); $target->delete();
        return back()->with('success','Target removed.');
    }

    public function convert(Request $request, Campaign $campaign, CampaignTarget $target): RedirectResponse
    {
        $this->authorizeCampaign($campaign); abort_unless($target->campaign_id===$campaign->id,404);
        $data=$request->validate(['converted_type'=>'required|in:lead,contact,deal','conversion_mode'=>'required|in:existing,new','existing_id'=>'nullable|integer','new_name'=>'nullable|string|max:255','owner_id'=>'required|integer','conversion_value'=>'nullable|numeric|min:0']);
        $map=['lead'=>Lead::class,'contact'=>Contact::class,'deal'=>Deal::class];
        $owner=User::whereKey($data['owner_id'])->where('business_id',$campaign->business_id)->firstOrFail();
        if($data['conversion_mode']==='existing'){
            abort_unless(filled($data['existing_id']??null),422,'Select a record to convert into.');
            $record=$map[$data['converted_type']]::whereKey($data['existing_id'])->where('business_id',$campaign->business_id)->firstOrFail();
        } else {
            abort_unless(filled($data['new_name']??null),422,'A name is required to create a new record.');
            $names=preg_split('/\s+/',trim($data['new_name']),2); $first=$names[0]; $last=$names[1]??'';
            $source=$target->target;
            $record=match($data['converted_type']) {
                'lead'=>Lead::create(['business_id'=>$campaign->business_id,'first_name'=>$first,'last_name'=>$last,'topic'=>$campaign->campaign_name,'lead_source'=>$campaign->campaign_name,'contact_owner_id'=>$owner->id,'stage_id'=>1,'status'=>'active']),
                'contact'=>Contact::create(['business_id'=>$campaign->business_id,'first_name'=>$first,'last_name'=>$last,'contact_owner_id'=>$owner->id,'type'=>'prospect','status'=>'active']),
                'deal'=>Deal::create(['business_id'=>$campaign->business_id,'name'=>$data['new_name'],'owner_id'=>$owner->id,'contact_id'=>$source instanceof Contact ? $source->id : null,'lead_id'=>$source instanceof Lead ? $source->id : null,'estimate_amount'=>$data['conversion_value']??0,'forecast_value'=>0,'close_probability'=>0,'stage_id'=>1,'status'=>'active']),
            };
        }
        $target->update(['converted'=>true,'converted_type'=>$map[$data['converted_type']],
            'converted_id'=>$record->id,'conversion_value'=>$data['conversion_value']??0,
            'response_status'=>'converted','responded_at'=>now(),'converted_at'=>now()]);
        \DB::table('campaign_conversion_attributions')->insert(['business_id'=>$campaign->business_id,'campaign_id'=>$campaign->id,'campaign_target_id'=>$target->id,'converted_type'=>$map[$data['converted_type']],'converted_id'=>$record->id,'owner_id'=>$owner->id,'conversion_value'=>$data['conversion_value']??0,'converted_at'=>now(),'created_at'=>now(),'updated_at'=>now()]);
        AuditLog::create(['business_id'=>$campaign->business_id,'user_id'=>$request->user()->id,'employee_name'=>$request->user()->name,'employee_email'=>$request->user()->email,'action'=>'campaign_audience_converted','entity_type'=>$map[$data['converted_type']],'entity_id'=>(string)$record->id,'route_name'=>$request->route()?->getName(),'method'=>$request->method(),'url'=>$request->path(),'response_status'=>200,'new_values'=>['campaign_id'=>$campaign->id,'campaign_name'=>$campaign->campaign_name,'audience_target_id'=>$target->id,'conversion_value'=>$data['conversion_value']??0,'owner_id'=>$owner->id],'performed_at'=>now()]);
        $campaign->update(['actual_revenue'=>$campaign->targets()->sum('conversion_value')]);
        return back()->with('success','Campaign conversion recorded.');
    }

    public function sync(Campaign $campaign,string $provider,CrmIntegrationService $service): RedirectResponse
    {
        $this->authorizeCampaign($campaign); abort_unless(in_array($provider,['facebook','mailchimp'],true),404);
        $log=IntegrationSyncLog::create(['business_id'=>$campaign->business_id,'provider'=>$provider,'direction'=>'outbound',
            'operation'=>'campaign_sync','status'=>'processing','payload'=>['campaign_id'=>$campaign->id],'attempts'=>1]);
        try{
            if($provider==='mailchimp') $count=$service->syncMailchimpCampaign($campaign);
            else{
                $count=$service->importFacebookLeads();
                Lead::where('business_id',$campaign->business_id)->where('lead_source','like','Facebook%')
                    ->where('topic',$campaign->campaign_name)->each(fn($lead)=>CampaignTarget::firstOrCreate(
                        ['campaign_id'=>$campaign->id,'target_type'=>Lead::class,'target_id'=>$lead->id],
                        ['business_id'=>$campaign->business_id,'provider'=>'facebook','delivery_status'=>'imported','responded_at'=>now()]
                    ));
            }
            $log->update(['status'=>'completed','completed_at'=>now()]);
            return back()->with('success',ucfirst($provider)." synchronization completed ({$count} records).");
        }catch(\Throwable $e){$log->update(['status'=>'failed','error'=>$e->getMessage()]);report($e);return back()->withErrors(['sync'=>$e->getMessage()]);}
    }

    public function retry(Campaign $campaign,IntegrationSyncLog $log,CrmIntegrationService $service): RedirectResponse
    {
        $this->authorizeCampaign($campaign); abort_unless((int)data_get($log->payload,'campaign_id')===$campaign->id,404);
        $log->update(['status'=>'retrying','attempts'=>$log->attempts+1,'error'=>null]);
        return $this->sync($campaign,$log->provider,$service);
    }

    private function authorizeCampaign(Campaign $campaign): void
    { abort_unless($campaign->business_id===auth()->user()->business_id,403); }
}
