<?php
namespace App\Controllers;

class CustomersController extends BaseController
{
    public function index()
    {
        if (!$this->can('view_customers')) return redirect()->to('/dashboard')->with('error','Access denied');

        $search = $this->request->getGet('search');
        $type   = $this->request->getGet('type');
        $status = $this->request->getGet('status') ?? 'active';
        $tab    = $this->request->getGet('tab') ?? 'active';

        $db = db_connect();
        $b  = $db->table('customers c')
                 ->select('c.*, GROUP_CONCAT(cp.number ORDER BY cp.is_primary DESC SEPARATOR ", ") as phones_list')
                 ->join('customer_phones cp','cp.customer_id = c.id','left')
                 ->where('c.company_id', $this->companyId)
                 ->groupBy('c.id');

        if ($tab === 'deleted') {
            $b->where('c.deleted_at IS NOT NULL',null,false);
        } else {
            $b->where('c.deleted_at IS NULL',null,false);
            if ($status) $b->where('c.status', $status);
        }

        if ($search) {
            $b->groupStart()
              ->like('c.first_name',$search)->orLike('c.last_name',$search)
              ->orLike('c.company_name',$search)->orLike('c.email',$search)
              ->orLike('c.ref',$search)
              ->groupEnd();
        }
        if ($type) $b->where('c.type', $type);

        $customers = $b->orderBy('c.last_name','ASC')->get()->getResultArray();

        $counts = [
            'active'  => $db->table('customers')->where('company_id',$this->companyId)->where('status','active')->where('deleted_at IS NULL',null,false)->countAllResults(),
            'inactive'=> $db->table('customers')->where('company_id',$this->companyId)->where('status','inactive')->where('deleted_at IS NULL',null,false)->countAllResults(),
            'deleted' => $db->table('customers')->where('company_id',$this->companyId)->where('deleted_at IS NOT NULL',null,false)->countAllResults(),
        ];

        return $this->view('customers/index', compact('customers','counts','tab','search','type','status'));
    }

    public function show(int $id)
    {
        if (!$this->can('view_customers')) return redirect()->to('/dashboard')->with('error','Access denied');
        $customer = $this->getCustomerOr404($id);

        $db = db_connect();

        $customer['phones']   = $db->table('customer_phones')->where('customer_id',$id)->orderBy('sort_order')->get()->getResultArray();
        $customer['addresses']= $db->table('customer_addresses')->where('customer_id',$id)->where('deleted_at IS NULL',null,false)->get()->getResultArray();
        $customer['contacts'] = $db->table('customer_contacts')->where('customer_id',$id)->orderBy('sort_order')->get()->getResultArray();
        $customer['tags']     = array_column($db->table('customer_tags')->where('customer_id',$id)->get()->getResultArray(),'tag');

        $jobs     = $db->table('jobs j')->select('j.*, js.name as status_name, js.color as status_color')->join('job_statuses js','js.id=j.status_id')->where('j.company_id',$this->companyId)->where('j.customer_id',$id)->where('j.deleted_at IS NULL',null,false)->orderBy('j.created_at','DESC')->get()->getResultArray();
        $quotes   = $db->table('quotes')->where('company_id',$this->companyId)->where('customer_id',$id)->where('deleted_at IS NULL',null,false)->orderBy('created_at','DESC')->get()->getResultArray();
        $invoices = $db->table('invoices')->where('company_id',$this->companyId)->where('customer_id',$id)->where('deleted_at IS NULL',null,false)->orderBy('created_at','DESC')->get()->getResultArray();
        $notes    = $db->table('notes')->where('company_id',$this->companyId)->where('entity_type','customer')->where('entity_id',$id)->where('deleted_at IS NULL',null,false)->orderBy('created_at','DESC')->get()->getResultArray();
        $files    = $db->table('files')->where('company_id',$this->companyId)->where('entity_type','customer')->where('entity_id',$id)->where('deleted_at IS NULL',null,false)->orderBy('created_at','DESC')->get()->getResultArray();

        $tab = $this->request->getGet('tab') ?? 'overview';

        return $this->view('customers/show', compact('customer','jobs','quotes','invoices','notes','files','tab'));
    }

    public function create()
    {
        if (!$this->can('edit_customers')) return redirect()->to('/customers')->with('error','Access denied');
        $custNext   = (int)(model('CompanySettingModel')->getSetting($this->companyId,'numbering','cust_next') ?? 1);
        $custPrefix = model('CompanySettingModel')->getSetting($this->companyId,'numbering','cust_prefix') ?? 'CUST-';
        $nextRef    = $custPrefix . str_pad($custNext, config('Fieldly')->numberPadding, '0', STR_PAD_LEFT);
        return $this->view('customers/create', ['nextRef' => $nextRef]);
    }

    public function store()
    {
        if (!$this->can('edit_customers')) return redirect()->to('/customers')->with('error','Access denied');

        $post  = $this->request->getPost();
        $rules = [
            'first_name' => 'required|min_length[1]|max_length[80]',
            'last_name'  => 'required|min_length[1]|max_length[80]',
            'email'      => 'permit_empty|valid_email',
        ];

        if (!$this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $db = db_connect();
        $id = model('CustomerModel')->insert([
            'company_id'   => $this->companyId,
            'ref'          => $this->nextNumber('cust_prefix','cust_next'),
            'type'         => $post['type'] ?? 'individual',
            'first_name'   => trim($post['first_name']),
            'last_name'    => trim($post['last_name']),
            'company_name' => trim($post['company_name'] ?? ''),
            'vat_number'   => trim($post['vat_number'] ?? ''),
            'email'        => trim($post['email'] ?? ''),
            'status'       => 'active',
            'notes'        => trim($post['notes'] ?? ''),
            'created_by'   => $this->userId,
            'created_at'   => date('Y-m-d H:i:s'),
            'updated_at'   => date('Y-m-d H:i:s'),
        ]);

        // Phones
        if (!empty($post['phones'])) {
            foreach ($post['phones'] as $i => $phone) {
                if (!empty($phone['number'])) {
                    $db->table('customer_phones')->insert(['customer_id'=>$id,'type'=>$phone['type']??'Mobile','number'=>trim($phone['number']),'is_primary'=>$i===0?1:0,'sort_order'=>$i]);
                }
            }
        }

        // Billing address
        if (!empty($post['billing_line1'])) {
            $db->table('customer_addresses')->insert([
                'customer_id'=>$id,'type'=>'billing','line1'=>$post['billing_line1']??'',
                'line2'=>$post['billing_line2']??'','town'=>$post['billing_town']??'',
                'county'=>$post['billing_county']??'','postcode'=>$post['billing_postcode']??'',
                'country'=>$post['billing_country']??'United Kingdom','is_primary'=>1,'is_default'=>1,
            ]);
        }

        $this->log('customer.created','customer',$id,"Customer created: {$post['first_name']} {$post['last_name']}");

        return redirect()->to("/customers/{$id}")->with('success','Customer created successfully.');
    }

    public function edit(int $id)
    {
        if (!$this->can('edit_customers')) return redirect()->to('/customers')->with('error','Access denied');
        $customer = $this->getCustomerOr404($id);
        $db = db_connect();
        $customer['phones']   = $db->table('customer_phones')->where('customer_id',$id)->orderBy('sort_order')->get()->getResultArray();
        $customer['addresses']= $db->table('customer_addresses')->where('customer_id',$id)->where('deleted_at IS NULL',null,false)->get()->getResultArray();
        return $this->view('customers/edit', compact('customer'));
    }

    public function update(int $id)
    {
        if (!$this->can('edit_customers')) return redirect()->to('/customers')->with('error','Access denied');
        $customer = $this->getCustomerOr404($id);
        $post = $this->request->getPost();

        db_connect()->table('customers')->where('id',$id)->update([
            'type'         => $post['type'] ?? $customer['type'],
            'first_name'   => trim($post['first_name']),
            'last_name'    => trim($post['last_name']),
            'company_name' => trim($post['company_name'] ?? ''),
            'vat_number'   => trim($post['vat_number'] ?? ''),
            'email'        => trim($post['email'] ?? ''),
            'status'       => $post['status'] ?? $customer['status'],
            'notes'        => trim($post['notes'] ?? ''),
            'updated_at'   => date('Y-m-d H:i:s'),
        ]);

        $db = db_connect();
        $db->table('customer_phones')->where('customer_id',$id)->delete();
        if (!empty($post['phones'])) {
            foreach ($post['phones'] as $i => $phone) {
                if (!empty($phone['number'])) {
                    $db->table('customer_phones')->insert(['customer_id'=>$id,'type'=>$phone['type']??'Mobile','number'=>trim($phone['number']),'is_primary'=>$i===0?1:0,'sort_order'=>$i]);
                }
            }
        }

        $this->log('customer.updated','customer',$id,"Customer updated: {$post['first_name']} {$post['last_name']}");
        return redirect()->to("/customers/{$id}")->with('success','Customer updated.');
    }

    public function delete(int $id)
    {
        if (!$this->can('edit_customers')) return redirect()->back()->with('error','Access denied');
        $customer = $this->getCustomerOr404($id);
        $summary  = "{$customer['first_name']} {$customer['last_name']}" . ($customer['company_name'] ? " · {$customer['company_name']}" : '');

        // Soft delete via raw query to avoid FK constraint issues
        db_connect()->table('customers')->where('id',$id)->update(['deleted_at' => date('Y-m-d H:i:s')]);

        // Log in deleted_items for recycle bin
        model('DeletedItemModel')->insert([
            'company_id'     => $this->companyId,
            'entity_type'    => 'customer',
            'entity_id'      => $id,
            'entity_ref'     => $customer['ref'] ?? null,
            'entity_summary' => $summary,
            'snapshot_json'  => json_encode($customer),
            'deleted_by'     => $this->userId,
        ]);

        $this->log('customer.deleted','customer',$id,"Customer deleted: {$summary}");
        return redirect()->to('/customers')->with('success','Customer moved to recycle bin.');
    }

    public function restore(int $id)
    {
        if (!$this->can('edit_customers')) return redirect()->back()->with('error','Access denied');
        $item = model('DeletedItemModel')->where('company_id',$this->companyId)->where('entity_type','customer')->where('entity_id',$id)->where('purged_at IS NULL',null,false)->first();
        if (!$item) return redirect()->back()->with('error','Not found in recycle bin.');
        db_connect()->table('customers')->where('id',$id)->update(['deleted_at' => null]);
        model('DeletedItemModel')->update($item['id'],['restored_at'=>date('Y-m-d H:i:s'),'restored_by'=>$this->userId]);
        return redirect()->to("/customers/{$id}")->with('success','Customer restored.');
    }

    public function addAddress(int $id)
    {
        if (!$this->can('edit_customers')) return redirect()->back()->with('error','Access denied');
        $this->getCustomerOr404($id);
        $post = $this->request->getPost();
        db_connect()->table('customer_addresses')->insert([
            'customer_id' => $id,
            'type'        => $post['type'] ?? 'site',
            'label'       => trim($post['label'] ?? ''),
            'line1'       => trim($post['line1'] ?? ''),
            'line2'       => trim($post['line2'] ?? ''),
            'town'        => trim($post['town'] ?? ''),
            'county'      => trim($post['county'] ?? ''),
            'postcode'    => trim($post['postcode'] ?? ''),
            'country'     => trim($post['country'] ?? 'United Kingdom'),
            'access_notes'=> trim($post['access_notes'] ?? ''),
            'is_primary'  => 0,
            'is_default'  => $post['is_default'] ?? 0,
        ]);
        return redirect()->to("/customers/{$id}?tab=addresses")->with('success','Address added.');
    }

    public function deleteAddress(int $customerId, int $addressId)
    {
        if (!$this->can('edit_customers')) return redirect()->back()->with('error','Access denied');
        db_connect()->table('customer_addresses')->where('id',$addressId)->where('customer_id',$customerId)->update(['deleted_at'=>date('Y-m-d H:i:s')]);
        return redirect()->to("/customers/{$customerId}?tab=addresses")->with('success','Address removed.');
    }

    public function addNote(int $id)
    {
        if (!$this->can('manage_notes')) return redirect()->back()->with('error','Access denied');
        $this->getCustomerOr404($id);
        $text = trim($this->request->getPost('text') ?? '');
        if (!$text) return redirect()->back()->with('error','Note cannot be empty.');
        db_connect()->table('notes')->insert(['company_id'=>$this->companyId,'entity_type'=>'customer','entity_id'=>$id,'text'=>$text,'is_internal'=>1,'created_by'=>$this->userId,'created_at'=>date('Y-m-d H:i:s')]);
        return redirect()->to("/customers/{$id}?tab=notes")->with('success','Note added.');
    }

    public function uploadFile(int $id)
    {
        if (!$this->can('manage_files')) return redirect()->back()->with('error','Access denied');
        $this->getCustomerOr404($id);
        $file = $this->request->getFile('file');
        if (!$file || !$file->isValid()) return redirect()->back()->with('error','No valid file.');
        $name = $file->getRandomName();
        $path = WRITEPATH.'uploads/'.$this->companyId.'/';
        if (!is_dir($path)) mkdir($path,0755,true);
        $file->move($path,$name);
        db_connect()->table('files')->insert(['company_id'=>$this->companyId,'entity_type'=>'customer','entity_id'=>$id,'filename'=>$name,'original_name'=>$file->getClientName(),'mime_type'=>$file->getClientMimeType(),'file_size'=>$file->getSize(),'disk'=>'local','disk_path'=>'uploads/'.$this->companyId.'/'.$name,'uploaded_by'=>$this->userId,'created_at'=>date('Y-m-d H:i:s')]);
        return redirect()->to("/customers/{$id}?tab=files")->with('success','File uploaded.');
    }

    private function getCustomerOr404(int $id): array
    {
        $customer = db_connect()->table('customers')->where('id',$id)->where('company_id',$this->companyId)->get()->getRowArray();
        if (!$customer) {
            throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
        }
        return $customer;
    }
}