<?php

namespace App\Http\Controllers\Agency\Customer;

use App\Http\Controllers\Controller;
use App\Models\Customer\Customer;
use App\Models\Customer\CustomerActivity;
use App\Models\Customer\CustomerFieldDefinition;
use App\Models\Customer\CustomerFieldValue;
use App\Models\Customer\CustomerDocumentType;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class CustomerController extends Controller
{
     use AuthorizesRequests;

     // ─── INDEX ────────────────────────────────────────────────────────────────

     public function index(Request $request)
     {
          $query = Customer::with(['assignedAgent'])
               ->withCount('passengers')
               ->byAgency(Auth::user()->currentAgencyId());

          // -- Özel Alan Filterable Tanımları
          $agencyId = Auth::user()->currentAgencyId();
          $filterableFields = CustomerFieldDefinition::byAgency($agencyId)->active()->where('is_filterable', true)->get();
          $listableFields = CustomerFieldDefinition::byAgency($agencyId)->active()->where('is_visible_in_list', true)->get();

          // -- Arama (Standart + Özel Alanlar)
          if ($request->filled('search')) {
               $term = $request->search;
               $searchableFieldsIds = CustomerFieldDefinition::byAgency($agencyId)
                    ->active()
                    ->where('is_searchable', true)
                    ->pluck('id');

               $query->where(function ($q) use ($term, $searchableFieldsIds) {
                    $q->where('first_name', 'like', "%{$term}%")
                         ->orWhere('last_name', 'like', "%{$term}%")
                         ->orWhere('emails', 'like', "%{$term}%")
                         ->orWhere('phone', 'like', "%{$term}%")
                         ->orWhere('company_name', 'like', "%{$term}%")
                         ->orWhereHas('customFieldValues', function ($sq) use ($term, $searchableFieldsIds) {
                              $sq->whereIn('field_definition_id', $searchableFieldsIds)
                                   ->where('value', 'like', "%{$term}%");
                         });
               });
          }

          // -- Standart Filtreler
          if ($request->filled('status')) {
               $query->where('status', $request->status);
          }
          if ($request->filled('type')) {
               $query->where('customer_type', $request->type);
          }
          if ($request->filled('priority')) {
               $query->where('priority', $request->priority);
          }
          if ($request->filled('segment')) {
               $query->where('customer_segment', $request->segment);
          }

          // -- Özel Alan Filtreleri
          foreach ($filterableFields as $field) {
               $paramName = 'cf_' . $field->field_key;
               if ($request->filled($paramName)) {
                    $val = $request->get($paramName);
                    $query->whereHas('customFieldValues', function ($sq) use ($field, $val) {
                         $sq->where('field_definition_id', $field->id);
                         if ($field->field_type === 'multiselect') {
                              $sq->where('value', 'like', '%"' . $val . '"%');
                         } else {
                              $sq->where('value', $val);
                         }
                    });
               }
          }

          if ($request->boolean('blacklisted')) {
               $query->blacklisted();
          }

          // -- Sıralama ve Yükleme
          $sortBy = $request->get('sort', 'created_at');
          $sortDir = $request->get('dir', 'desc');
          $query->orderBy($sortBy, $sortDir);

          // Eager load values for listable fields
          $customers = $query->with(['customFieldValues.fieldDefinition'])->paginate(20)->withQueryString();

          // Özet istatistikler (liste sayfası için)
          $stats = [
               'total' => Customer::byAgency(Auth::user()->currentAgencyId())->count(),
               'active' => Customer::byAgency(Auth::user()->currentAgencyId())->active()->count(),
               'priority' => Customer::byAgency(Auth::user()->currentAgencyId())->isPriority()->count(),
               'potential' => Customer::byAgency(Auth::user()->currentAgencyId())->potential()->count(),
          ];

          return view('agency.customers.index', compact('customers', 'stats', 'filterableFields', 'listableFields'));
     }

     // ─── CREATE / STORE ───────────────────────────────────────────────────────

     public function create()
     {
          $agencyId = Auth::user()->currentAgencyId();
          $agents = \App\Models\User::byAgency($agencyId)
               ->active()
               ->orderBy('first_name')
               ->get();

          $definitions = CustomerFieldDefinition::byAgency($agencyId)
               ->active()
               ->orderBy('sort_order')
               ->get();

          return view('agency.customers.create', compact('agents', 'definitions'));
     }

     public function store(Request $request)
     {
          $agencyId = Auth::user()->currentAgencyId();
          $requiredFields = CustomerFieldDefinition::byAgency($agencyId)->active()->where('is_required', true)->get();

          $rules = [
               'first_name' => 'required|string|max:100',
               'last_name' => 'required|string|max:100',
               'emails' => 'nullable|array',
               'emails.*' => 'nullable|email|max:255',
               'phone' => 'nullable|string|max:20',
               'phone_alt' => 'nullable|string|max:20',
               'birth_date' => 'nullable|date',
               'gender' => 'nullable|in:male,female,other',
               'national_id' => 'nullable|string|max:20',
               'passport_number' => 'nullable|string|max:20',
               'passport_expiry' => 'nullable|date',
               'nationality' => 'nullable|string|size:2',
               'address' => 'nullable|string',
               'city' => 'nullable|string|max:100',
               'district' => 'nullable|string|max:100',
               'country' => 'nullable|string|size:2',
               'postal_code' => 'nullable|string|max:10',
               'customer_type' => 'required|in:individual,corporate',
               'status' => 'required|in:active,inactive,blocked,potential',
               'priority' => 'boolean',
               'company_name' => 'nullable|string|max:255',
               'company_tax_number' => 'nullable|string|max:50',
               'company_tax_office' => 'nullable|string|max:100',
               'company_position' => 'nullable|string|max:100',
               'preferred_contact_method' => 'nullable|string|in:email,phone,sms',
               'email_marketing' => 'boolean',
               'sms_marketing' => 'boolean',
               'assigned_agent_id' => 'nullable|exists:users,id',
               'credit_limit' => 'nullable|numeric|min:0',
               'payment_term_days' => 'nullable|integer|min:0',
               'default_discount_rate' => 'nullable|numeric|min:0|max:100',
               'referral_source' => 'nullable|string|max:100',
               'internal_notes' => 'nullable|string',
          ];

          // Dinamik Zorunlu Alanlar (EAV için)
          $customAttributes = [];
          foreach ($requiredFields as $field) {
               $rules['custom_fields.' . $field->id] = 'required';
               $customAttributes['custom_fields.' . $field->id] = $field->label;
          }

          try {
               $validated = $request->validate($rules, [], $customAttributes);
               $validated['agency_id'] = $agencyId;

               // Tags ve Interests'i array'e dönüştür (eğer string olarak geldiyse)
               if (isset($validated['tags']) && is_string($validated['tags'])) {
                    $validated['tags'] = array_filter(array_map('trim', explode(',', $validated['tags'])));
               }
               if (isset($validated['interests']) && is_string($validated['interests'])) {
                    $validated['interests'] = array_filter(array_map('trim', explode(',', $validated['interests'])));
               }

               DB::beginTransaction();

               // Ana Müşteri Kaydı
               $customer = Customer::create(collect($validated)->except('custom_fields')->toArray());

               // Özel Alan Değerlerini Kaydet
               if ($request->has('custom_fields')) {
                    foreach ($request->custom_fields as $defId => $value) {
                         if ($value !== null && $value !== '') {
                              // multiselect ise JSON sakla
                              if (is_array($value)) {
                                   $value = json_encode(array_values($value));
                              }
                              CustomerFieldValue::setValue($customer->id, (int) $defId, $value);
                         }
                    }
               }

               DB::commit();

               return redirect()
                    ->route('agency.customers.show', $customer)
                    ->with('success', 'Müşteri başarıyla oluşturuldu.');

          } catch (\Illuminate\Validation\ValidationException $e) {
               Log::warning('Müşteri oluşturma validasyon hatası', [
                    'errors' => $e->errors(),
                    'input' => $request->except(['password', 'password_confirmation'])
               ]);
               throw $e;
          } catch (\Exception $e) {
               DB::rollBack();
               Log::error('Müşteri oluşturulurken hata meydana geldi: ' . $e->getMessage(), [
                    'exception' => $e,
                    'input' => $request->all()
               ]);
               return back()
                    ->withInput()
                    ->with('error', 'Hata: ' . $e->getMessage());
          }
     }

     // ─── SHOW ─────────────────────────────────────────────────────────────────

     public function show(Customer $customer)
     {
          $this->authorizeAgency($customer);
          return redirect()->route('agency.customers.index', ['open_customer_id' => $customer->id]);
     }

     // ─── EDIT / UPDATE ────────────────────────────────────────────────────────

     public function edit(Customer $customer)
     {
          $this->authorizeAgency($customer);
          return redirect()->route('agency.customers.index', ['open_customer_id' => $customer->id, 'tab' => 'details']);
     }

     public function update(Request $request, Customer $customer)
     {
          $this->authorizeAgency($customer);

          $agencyId = Auth::user()->currentAgencyId();
          $requiredFields = CustomerFieldDefinition::byAgency($agencyId)->active()->where('is_required', true)->get();

          $rules = [
               // Kişisel
               'first_name' => 'required|string|max:100',
               'last_name' => 'required|string|max:100',
               'emails' => 'nullable|array',
               'emails.*' => 'nullable|email|max:255',
               'phone' => 'nullable|string|max:20',
               'phone_alt' => 'nullable|string|max:20',
               'birth_date' => 'nullable|date',
               'gender' => 'nullable|in:male,female,other',
               'national_id' => 'nullable|string|max:20',
               'passport_number' => 'nullable|string|max:20',
               'passport_expiry' => 'nullable|date',
               'nationality' => 'nullable|string|max:10',

               // Adres
               'address' => 'nullable|string',
               'city' => 'nullable|string|max:100',
               'district' => 'nullable|string|max:100',
               'country' => 'nullable|string|max:10',
               'postal_code' => 'nullable|string|max:10',

               // Tip & Durum
               'customer_type' => 'required|in:individual,corporate',
               'status' => 'required|in:active,inactive,blocked,potential',
               'priority' => 'boolean',

               // Kurumsal
               'company_name' => 'nullable|string|max:255',
               'company_type' => 'nullable|string|max:100',
               'company_tax_number' => 'nullable|string|max:50',
               'company_tax_office' => 'nullable|string|max:100',
               'company_position' => 'nullable|string|max:100',

               // Fatura
               'billing_address' => 'nullable|string',
               'billing_city' => 'nullable|string|max:100',
               'billing_district' => 'nullable|string|max:100',
               'billing_tax_number' => 'nullable|string|max:50',
               'billing_tax_office' => 'nullable|string|max:100',
               'billing_email' => 'nullable|email|max:255',

               // İletişim
               'preferred_contact_method' => 'nullable|string|in:email,phone,sms',
               'email_marketing' => 'boolean',
               'sms_marketing' => 'boolean',

               // Atama
               'assigned_agent_id' => 'nullable|exists:users,id',

               // Finansal
               'credit_limit' => 'nullable|numeric|min:0',
               'payment_term_days' => 'nullable|integer|min:0',
               'default_discount_rate' => 'nullable|numeric|min:0|max:100',

               // Diğer
               'referral_source' => 'nullable|string|max:100',
               'internal_notes' => 'nullable|string',
          ];

          // Dinamik Zorunlu Alanlar (EAV için)
          $customAttributes = [];
          foreach ($requiredFields as $field) {
               $rules['custom_fields.' . $field->id] = 'required';
               $customAttributes['custom_fields.' . $field->id] = $field->label;
          }

          $validated = $request->validate($rules, [], $customAttributes);

          DB::beginTransaction();
          try {
               $customer->update(collect($validated)->except('custom_fields')->toArray());

               // Özel Alan Değerlerini Kaydet
               if ($request->has('custom_fields')) {
                    foreach ($request->custom_fields as $defId => $value) {
                         if ($value !== null && $value !== '') {
                              if (is_array($value)) {
                                   $value = json_encode(array_values($value));
                              }
                              CustomerFieldValue::setValue($customer->id, (int) $defId, $value);
                         } else {
                              CustomerFieldValue::where('customer_id', $customer->id)
                                   ->where('field_definition_id', $defId)
                                   ->delete();
                         }
                    }
               }

               DB::commit();
               return back()->with('success', 'Müşteri bilgileri başarıyla güncellendi.');
          } catch (\Exception $e) {
               DB::rollBack();
               return back()->with('error', 'Güncelleme sırasında hata oluştu: ' . $e->getMessage());
          }
     }

     // ─── DELETE ───────────────────────────────────────────────────────────────

     public function destroy(Customer $customer)
     {
          $this->authorizeAgency($customer);

          DB::beginTransaction();
          try {
               $customer->activities()->delete();
               $customer->delete();
               DB::commit();
          } catch (\Exception $e) {
               DB::rollBack();
               return back()->with('error', 'Müşteri silinirken bir hata oluştu.');
          }

          return redirect()
               ->route('agency.customers.index')
               ->with('success', 'Müşteri başarıyla silindi.');
     }

     // ─── QUICK ACTIONS ────────────────────────────────────────────────────────

     public function toggleStatus(Customer $customer)
     {
          $this->authorizeAgency($customer);

          $newStatus = $customer->status === 'active' ? 'inactive' : 'active';
          $customer->update(['status' => $newStatus]);

          return response()->json([
               'success' => true,
               'status' => $newStatus,
               'label' => $customer->fresh()->status_label,
               'message' => $newStatus === 'active' ? 'Müşteri aktif edildi.' : 'Müşteri pasif edildi.',
          ]);
     }

     public function toggleBlacklist(Request $request, Customer $customer)
     {
          $this->authorizeAgency($customer);

          if ($customer->blacklisted) {
               $customer->update([
                    'blacklisted' => false,
                    'blacklist_reason' => null,
                    'blacklisted_at' => null,
                    'blacklisted_by' => null,
                    'status' => 'active',
               ]);
               $message = 'Müşteri kara listeden çıkarıldı.';
          } else {
               $request->validate([
                    'blacklist_reason' => 'required|string|max:500',
               ]);

               $customer->update([
                    'blacklisted' => true,
                    'blacklist_reason' => $request->blacklist_reason,
                    'blacklisted_at' => now(),
                    'blacklisted_by' => Auth::id(),
                    'status' => 'blocked',
               ]);
               $message = 'Müşteri kara listeye alındı.';
          }

          return back()->with('success', $message);
     }

     public function updateLoyaltyPoints(Request $request, Customer $customer)
     {
          $this->authorizeAgency($customer);

          $request->validate([
               'points' => 'required|integer|min:1',
               'operation' => 'required|in:add,deduct',
               'note' => 'nullable|string|max:255',
          ]);

          if ($request->operation === 'add') {
               $customer->addLoyaltyPoints($request->points);
               $message = "{$request->points} puan eklendi.";
          } else {
               $customer->deductLoyaltyPoints($request->points);
               $message = "{$request->points} puan düşüldü.";
          }

          return back()->with('success', $message);
     }

     public function assignAgent(Request $request, Customer $customer)
     {
          $this->authorizeAgency($customer);

          $request->validate([
               'agent_id' => 'nullable|exists:users,id',
          ]);

          $customer->update(['assigned_agent_id' => $request->agent_id]);

          return response()->json([
               'success' => true,
               'message' => $request->agent_id ? 'Temsilci atandı.' : 'Temsilci ataması kaldırıldı.',
          ]);
     }

     public function bulkDelete(Request $request)
     {
          $request->validate([
               'ids' => 'required|array',
               'ids.*' => 'integer|exists:customers,id',
          ]);

          $agencyId = Auth::user()->currentAgencyId();

          DB::beginTransaction();
          try {
               $customers = Customer::byAgency($agencyId)
                    ->whereIn('id', $request->ids)
                    ->get();

               foreach ($customers as $customer) {
                    $customer->activities()->delete();
                    $customer->delete();
               }

               DB::commit();
          } catch (\Exception $e) {
               DB::rollBack();
               return response()->json(['success' => false, 'message' => 'Silme sırasında hata oluştu.'], 500);
          }

          return response()->json([
               'success' => true,
               'message' => count($request->ids) . ' müşteri silindi.',
          ]);
     }

     public function bulkStatus(Request $request)
     {
          $request->validate([
               'ids' => 'required|array',
               'ids.*' => 'integer|exists:customers,id',
               'status' => 'required|in:active,inactive,blocked,potential',
          ]);

          Customer::byAgency(Auth::user()->currentAgencyId())
               ->whereIn('id', $request->ids)
               ->update(['status' => $request->status]);

          return response()->json([
               'success' => true,
               'message' => count($request->ids) . ' müşterinin durumu güncellendi.',
          ]);
     }

     public function search(Request $request)
     {
          $term = $request->get('q', '');
          $agencyId = Auth::user()->currentAgencyId();

          $customers = Customer::byAgency($agencyId)
               ->where(function ($q) use ($term) {
                    $q->where('first_name', 'like', "%{$term}%")
                         ->orWhere('last_name', 'like', "%{$term}%")
                         ->orWhere('emails', 'like', "%{$term}%")
                         ->orWhere('phone', 'like', "%{$term}%")
                         ->orWhere('company_name', 'like', "%{$term}%");
               })
               ->active()
               ->limit(20)
               ->get(['id', 'first_name', 'last_name', 'emails', 'phone', 'customer_type'])
               ->map(fn($c) => [
                    'id' => $c->id,
                    'text' => "{$c->full_name}" . ($c->email ? " — {$c->email}" : ''),
                    'type' => $c->customer_type,
               ]);

          return response()->json(['results' => $customers]);
     }

     /** AJAX Hızlı Önizleme (Drawer için) */
     public function quickView(Customer $customer)
     {
          $this->authorizeAgency($customer);

          $customer->load([
               'assignedAgent',
               'passengers',
               'customerDocuments.type',
               'customerDocuments.creator',
               'reservations' => function($q) {
                    $q->with(['productType'])->latest('start_date');
               },
               'customFieldValues.fieldDefinition'
          ]);

          $recentActivities = CustomerActivity::where('customer_id', $customer->id)
               ->with(['performedBy', 'assignedTo'])
               ->latest('activity_date')
               ->limit(10)
               ->get();

          $activityStats = [
               'total' => CustomerActivity::where('customer_id', $customer->id)->count(),
               'pending' => CustomerActivity::where('customer_id', $customer->id)->pending()->count(),
               'follow_up' => CustomerActivity::where('customer_id', $customer->id)->requiresFollowUp()->count(),
               'complaints' => CustomerActivity::where('customer_id', $customer->id)->complaint()->count(),
          ];

          $agencyId = Auth::user()->currentAgencyId();
          $documentTypes = CustomerDocumentType::byAgency($agencyId)->active()->orderBy('sort_order')->get();
          
          // Get all custom field definitions to show empty ones too
          $definitions = CustomerFieldDefinition::byAgency($agencyId)
               ->active()
               ->orderBy('sort_order')
               ->get();

          // Financial summary
          $financial = [
               'total_spent' => $customer->reservations->sum('total_amount'),
               'total_paid' => $customer->reservations->sum('paid_amount'),
               'balance' => $customer->reservations->sum('remaining_amount'),
               'bookings_count' => $customer->reservations->count(),
          ];

          return view('agency.customers.quick-view', compact('customer', 'recentActivities', 'activityStats', 'documentTypes', 'definitions', 'financial'))->render();
     }

     public function updateField(Request $request, Customer $customer)
     {
          $this->authorizeAgency($customer);

          $request->validate([
               'field' => 'required|string',
               'value' => 'nullable',
          ]);

          $field = $request->field;
          $value = $request->value;

          if (str_starts_with($field, 'custom_field_')) {
               $defId = (int) str_replace('custom_field_', '', $field);
               $def = CustomerFieldDefinition::where('agency_id', $customer->agency_id)->findOrFail($defId);
               
               if ($def->field_type === 'multiselect' && is_array($value)) {
                    $value = json_encode(array_values($value));
               }

               CustomerFieldValue::setValue($customer->id, $defId, $value);

               return response()->json([
                    'success' => true,
                    'message' => 'Özel alan güncellendi.',
                    'value' => $value,
                    'display_value' => $def->formatValue($value)
               ]);
          }

          $allowedFields = [
               'first_name', 'last_name', 'emails', 'phone', 'phone_alt',
               'national_id', 'passport_number', 'passport_expiry',
               'birth_date', 'gender', 'nationality', 'address', 'city',
               'district', 'country', 'postal_code', 'status', 'priority',
               'customer_type', 'company_name', 'company_type', 'company_tax_number',
               'company_tax_office', 'company_position', 'internal_notes',
               'preferred_contact_method', 'referral_source',
               'billing_address', 'billing_city', 'billing_district',
               'billing_tax_number', 'billing_tax_office', 'billing_email'
          ];

          if (!in_array($field, $allowedFields)) {
               return response()->json(['success' => false, 'message' => 'Bu alan güncellenemez.'], 422);
          }

          if ($field === 'emails' && $value) {
                if (is_string($value)) {
                    $value = array_filter(array_map('trim', explode(',', $value)));
                }
                $request->merge(['value' => $value]);
                $request->validate(['value' => 'array', 'value.*' => 'email|max:255']);
          }

          if (in_array($field, ['birth_date', 'passport_expiry']) && $value) {
               $request->validate(['value' => 'date']);
          }

          try {
               $customer->update([$field => $value]);

               $displayValue = $value;
               if ($field === 'status') $displayValue = $customer->fresh()->status_label;
               if ($field === 'priority') $displayValue = $customer->fresh()->priority_label;
               if ($field === 'gender') $displayValue = $value ? ['male' => 'Erkek', 'female' => 'Kadın', 'other' => 'Diğer'][$value] : '—';
               if ($field === 'preferred_contact_method') $displayValue = $value ? ucfirst($value) : '—';

               return response()->json([
                    'success' => true,
                    'message' => 'Güncellendi.',
                    'value' => $value,
                    'display_value' => $displayValue
               ]);
          } catch (\Exception $e) {
               return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
          }
     }

     protected function authorizeAgency(Customer $customer): void
     {
          if ($customer->agency_id !== Auth::user()->currentAgencyId()) {
               abort(403, 'Bu müşteriye erişim yetkiniz yok.');
          }
     }
}
