<?php

namespace App\Models;

use App\Models\Customer\Address;
use App\Traits\HasUuid;
use DB;
use Illuminate\Support\Facades\Storage;
use Barryvdh\DomPDF\Facade\Pdf;

class Estimate extends BaseModel
{
    use HasUuid;

    protected $primaryKey = 'estimate_id';
    protected $table = 'estimates';

    protected $fillable = [
        'estimate_number',
        'user_id',
        'customer_id',
        'customer_address_id',
        'interior_designer_id',
        'notes',
        'estimate_generated_at'
    ];

    const STORAGE_DISK = 'estimates';

    public function joinUser()
    {
        $userObj = new \App\Models\User;
        $userTable = $userObj->getTable();

        $this->queryBuilder->join($userTable, function ($join) use ($userTable) {
            $join->on($this->table . '.user_id', '=', $userTable . '.user_id');
        });
        return $this;
    }


    public function joinCustomer()
    {
        $customerObj = new \App\Models\Customer;
        $customerTable = $customerObj->getTable();

        $this->queryBuilder->join($customerTable, function ($join) use ($customerTable) {
            $join->on($this->table . '.customer_id', '=', $customerTable . '.customer_id');
        });
        return $this;
    }

    public function joinCustomerAddress()
    {
        $customerAddressObj = new \App\Models\Customer\Address;
        $customerAddressTable = $customerAddressObj->getTable();

        $this->queryBuilder->join($customerAddressTable, function ($join) use ($customerAddressTable) {
            $join->on($this->table . '.customer_address_id', '=', $customerAddressTable . '.customer_address_id');
        });

        return $this;
    }

    public function joinInteriorDesigner()
    {
        $designerObj = new \App\Models\InteriorDesigner;
        $designerTable = $designerObj->getTable();

        $this->queryBuilder->leftJoin($designerTable, function ($join) use ($designerTable) {
            $join->on($this->table . '.interior_designer_id', '=', $designerTable . '.interior_designer_id');
        });

        return $this;
    }

    public function getGridColumns($type = 'main')
    {
        $columns = [];
        $columns[] = ['label' => 'Estimate Number', 'field' => 'estimate_number_display'];
        $columns[] = ['label' => 'Customer', 'field' => 'customer_name'];
        $columns[] = ['label' => 'Address', 'field' => 'customer_address', 'html' => true];
        return $columns;
    }

    public function getEstimateNumberFormatQuery()
    {
        $prefix = '#EST-';
        $paddingZero = 4;
        return DB::raw("CONCAT('$prefix', $this->table.estimate_number) as estimate_number_display");
    }

    public function generateEstimateNumberForUser()
    {
        $count = $this->setSelect()->addFieldToFilter($this->table, 'user_id', '=', $this->getAuthId())->get()->count();
        $count += 1;
        return $count;
    }


    public function getDetails($estimate_id)
    {
        $response = ['success' => false, 'data' => []];
        $estimateData = $this->list(['estimate_id' => $estimate_id])->first();
        if (!empty($estimateData)) {
            $response['success'] = true;
            $response['data'] = $estimateData;
        }
        return $response;
    }

    public function list($data = [])
    {

        $customerObj = new \App\Models\Customer;
        $customerTable = $customerObj->getTable();

        $customerAddressObj = new \App\Models\Customer\Address;
        $customerAddressTable = $customerAddressObj->getTable();

        $userObj = new \App\Models\User;
        $userTable = $userObj->getTable();

        $interiorDesignerObj = new \App\Models\InteriorDesigner;
        $interiorDesignerTable = $interiorDesignerObj->getTable();

        $selectedColumns = [
            "$this->table.estimate_id as id",
            "$this->table.*",
            "$customerTable.name as customer_name",
            "$userTable.name as user_name",
            "$userTable.email as user_email",
            "$userTable.mobile as user_mobile",
            "$userTable.business_name",
            "$userTable.business_logo",
            "$customerTable.mobile as customer_mobile",
            "$customerTable.email as customer_email",
            "$interiorDesignerTable.name as interior_designer_name",
            "$interiorDesignerTable.mobile as interior_designer_mobile",
            "$interiorDesignerTable.email as interior_designer_email",
            $this->getEstimateNumberFormatQuery(),
            DB::raw("CONCAT($customerAddressTable.address_line_1,'<br>',$customerAddressTable.address_line_2,'<br>',$customerAddressTable.state,', ',$customerAddressTable.city,' - ',$customerAddressTable.postal_code,'<br>',$customerAddressTable.country) as customer_address")
        ];
        $this->setSelect();
        $this->joinUser();
        $this->joinCustomer();
        $this->joinInteriorDesigner();
        $this->joinCustomerAddress();
        $this->addFieldToFilter($userTable, 'user_id', '=', $this->getAuthId());
        if (!empty($data['estimate_id'])) {
            $this->addFieldToFilter($this->table, 'estimate_id', '=', $data['estimate_id']);
        }
        $this->addOrderby($this->table, 'estimate_number', 'desc');
        $estimates = $this->get($selectedColumns);

        if (!empty($estimates) && count($estimates) > 0) {

            $estimateSectionObj = new \App\Models\Estimate\Section;
            foreach ($estimates as $estimate) {
                if (request()->get('with') == 'items') {
                    $estimate->sections = $estimateSectionObj->getSectionsByEstimate($estimate->estimate_id);
                }
            }
        }
        return $estimates;
    }

    public function saveRecord($data = [])
    {

        $response = ['success' => false, 'message' => 'Failed to create Estimate.'];
        $customer_id = $data['customer_id'];
        $address_id = $data['address']['customer_address_id'];
        $interior_designer_id = !empty($data['interior_designer_id']) ? $data['interior_designer_id'] : null;
        if (empty($data['address']['customer_address_id'])) {
            $addressObj = new Address;
            $data['address']['customer_id'] = $data['customer_id'];
            $adrs = $addressObj->saveRecord($data['address']);
            if ($adrs['success']) {
                $address_id = $adrs['customer_address_id'];
            }
        }

        $estimateData = [
            'customer_id' => $customer_id,
            'estimate_number' => $this->generateEstimateNumberForUser(),
            'customer_address_id' => $address_id,
            'interior_designer_id' => $interior_designer_id
        ];
        $this->addAuthId($estimateData);
        $estimate = self::create($estimateData);
        $response['success'] = true;
        $response['message'] = 'Estimate created successfully.';
        $response['estimate_id'] = $estimate->estimate_id;
        return $response;
    }

    public function updateNotes($estimate_id, $notes = '')
    {
        $response = ['success' => false, 'message' => 'Failed to create Estimate.'];
        $estimate = $this->load($estimate_id);
        if ($estimate) {
            $estimate->notes = $notes;
            $estimate->save();
            $response['success'] = true;
            $response['message'] = 'Notes updated';
        }
        return $response;
    }

    public function getPdf($estimate_id)
    {
        $estimate = $this->load($estimate_id);
        if ($estimate) {
            $fileName = "$estimate_id.pdf";
            $needToGenerate = true;
            if ($needToGenerate) {
                request()->merge(['with' => 'items']);
                $estimateDetails = $this->getDetails($estimate_id)['data']->toArray();
                $pdf = Pdf::loadView('pdf.estimate', $estimateDetails);                
                Storage::disk('estimates')->put("$estimate_id.pdf", $pdf->output());
                $estimate->update(['estimate_generated_at' => \Carbon\Carbon::now()]);
            }
            return response()->download(Storage::disk('estimates')->path($fileName), $fileName);
        }
    }
}
