<?php

namespace App\Http\Controllers;

use App\Models\LeadSale;
use App\Traits\ApiResponse;
use App\Traits\ResolvesAccessibleUserIds;
use DB;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;

class LeadSaleController extends Controller
{
    use ApiResponse, ResolvesAccessibleUserIds;

    private function sale_data_format($data)
    {
        $creatorId = $data->created_by;
        $assigneeId = $data->assigned_to;

        /*
        |--------------------------------------------------------------------------
        | Share Calculation
        |--------------------------------------------------------------------------
        */

        if (
            !$assigneeId ||
            $creatorId == $assigneeId
        ) {

            $creatorShare = 100;
            $assigneeShare = 0;

            $creatorAmount = $data->total;
            $assigneeAmount = 0;

        } else {

            $creatorShare = 50;
            $assigneeShare = 50;

            $creatorAmount = $data->total * 0.5;
            $assigneeAmount = $data->total * 0.5;
        }

        return [
            'id' => $data->id,
            'product' => $data->product ? [
                'id' => $data->product->id,
                'name' => $data->product->name,
                'description' => $data->product->description,
            ] : null,
            'creator' => $data->creator ? [
                'id' => $data->creator->id,
                'name' => $data->creator->name,
                'email' => $data->creator->email,
                'country_code' => $data->creator->country_code,
                'phone' => $data->creator->phone,
                'image_path' => $data->creator->image_path ? Storage::disk('public')->url($data->creator->image_path) : null,
                'share_percentage' => $creatorShare,
                'sale_amount' => (float)$creatorAmount,
            ] : null,
            'assignee' => $data->assignee ? [
                'id' => $data->assignee->id,
                'name' => $data->assignee->name,
                'email' => $data->assignee->email,
                'country_code' => $data->assignee->country_code,
                'phone' => $data->assignee->phone,
                'image_path' => $data->assignee->image_path ? Storage::disk('public')->url($data->assignee->image_path) : null,
                'share_percentage' => $assigneeShare,
                'sale_amount' => (float)$assigneeAmount,
            ] : null,
            'sales_person' => $data->sales_person ? [
                'id' => $data->sales_person->id,
                'name' => $data->sales_person->name,
                'email' => $data->sales_person->email,
                'country_code' => $data->sales_person->country_code,
                'phone' => $data->sales_person->phone,
                'image_path' => $data->sales_person->image_path ? Storage::disk('public')->url($data->sales_person->image_path) : null,
            ] : null,
            'lead' => $data->lead ? [
                'id' => $data->lead->id,
                'name' => $data->lead->name,
                'email' => $data->lead->email,
                'country_code' => $data->lead->country_code,
                'phone' => $data->lead->phone,
                'company_name' => $data->lead->company->name,
            ] : null,
            'sale_date' => $data->sale_date,
            'price' => $data->price,
            'quantity' => $data->quantity,
            'total' => $data->total,
            'payment' => $data->payment_type->name ? [
                'id' => $data->payment_type->id,
                'name' => $data->payment_type->name,
            ] :null,
            'remarks' => $data->remarks,
            'incentive' => $data->incentive,
            'created_at' => $data->created_at,
            'updated_at' => $data->updated_at,
        ];
    }

    public function update_lead_sale(Request $request)
    {
        $user = $request->user();

        $hasUpdate = $user->can('report_management.sales.update');
        $hasOverride = $user->can('report_management.sales.override');

        if (!$hasUpdate && !$hasOverride) {
            return $this->error('Forbidden.', 403);
        }

        if (!$request->id && $request->sale_id) {
            $request->merge([
                'id' => $request->sale_id,
            ]);
        }

        $validated = $request->validate([
            'id' => ['required', 'integer', 'exists:lead_sales,id'],
            'product_id' => ['required', 'exists:products,id'],
            'price' => ['required', 'numeric', 'min:0'],
            'quantity' => ['required', 'numeric', 'min:0'],
            'total' => ['required', 'numeric', 'min:0'],
            'payment_type' => ['required', 'integer', 'exists:payment_types,id'],
            'remarks' => ['nullable', 'string'],
            'incentive' => ['nullable', 'numeric', 'min:0'],
            'sale_date' => ['nullable', 'date'],
        ]);

        $accessibleUserIds = $this->accessibleUserIdsFor(
            $user,
            'report_management.sales.override'
        );

        $sale = LeadSale::where('id', $validated['id'])
            ->where('is_deleted', 0)
            ->where(function ($query) use ($accessibleUserIds) {
                $query->whereIn('created_by', $accessibleUserIds)
                    ->orWhereIn('assigned_to', $accessibleUserIds);
            })
            ->first();

        if (!$sale) {
            return $this->error('Lead sale not found.', 404);
        }

        try {
            DB::beginTransaction();

            $oldData = $sale->only([
                'product_id',
                'price',
                'quantity',
                'total',
                'payment_type_id',
                'remarks',
                'incentive',
                'sale_date',
            ]);

            $sale->update([
                'product_id' => $validated['product_id'],
                'price' => $validated['price'],
                'quantity' => $validated['quantity'],
                'total' => $validated['total'],
                'payment_type_id' => $validated['payment_type'],
                'remarks' => $validated['remarks'] ?? null,
                'incentive' => $validated['incentive'] ?? $sale->incentive,
                'sale_date' => $validated['sale_date'] ?? $sale->sale_date,
                'updated_at' => now()->toDateTimeString(),
            ]);

            if ($sale->wasChanged()) {
                activity('sale_management')
                    ->performedOn($sale)
                    ->causedBy($user)
                    ->withProperties([
                        'old' => $oldData,
                        'new' => $sale->only([
                            'product_id',
                            'price',
                            'quantity',
                            'total',
                            'payment_type_id',
                            'remarks',
                            'incentive',
                            'sale_date',
                        ]),
                        'ip' => $request->ip(),
                        'user_agent' => $request->userAgent(),
                    ])
                    ->log("Sale record #{$sale->id} was updated by {$user->name}.");
            }

            DB::commit();

            return $this->success(
                'Lead sale updated successfully.',
                $sale->load(['creator', 'assignee', 'product', 'lead', 'payment_type'])
            );

        } catch (\Throwable $e) {
            DB::rollBack();

            return $this->error($e->getMessage(), 500);
        }
    }

    public function delete_lead_sale(Request $request)
    {
        $user = $request->user();

        $hasDelete = $user->can('report_management.sales.delete');
        $hasOverride = $user->can('report_management.sales.override');

        if (!$hasDelete && !$hasOverride) {
            return $this->error('Forbidden.', 403);
        }

        if (!$request->id && $request->sale_id) {
            $request->merge([
                'id' => $request->sale_id,
            ]);
        }

        $validated = $request->validate([
            'id' => ['required', 'integer', 'exists:lead_sales,id'],
        ]);

        $accessibleUserIds = $this->accessibleUserIdsFor(
            $user,
            'report_management.sales.override'
        );

        $sale = LeadSale::where('id', $validated['id'])
            ->where('is_deleted', 0)
            ->where(function ($query) use ($accessibleUserIds) {
                $query->whereIn('created_by', $accessibleUserIds)
                    ->orWhereIn('assigned_to', $accessibleUserIds);
            })
            ->first();

        if (!$sale) {
            return $this->error('Lead sale not found or already deleted.', 404);
        }

        try {
            DB::beginTransaction();

            $sale->update([
                'is_deleted' => 1,
                'deleted_at' => now()->toDateTimeString(),
                'updated_at' => now()->toDateTimeString(),
            ]);

            activity('sale_management')
                ->performedOn($sale)
                ->causedBy($user)
                ->withProperties([
                    'sale_id' => $sale->id,
                    'lead_id' => $sale->lead_id,
                    'product_id' => $sale->product_id,
                    'total' => $sale->total,
                    'deleted_at' => $sale->deleted_at,
                    'ip' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                ])
                ->log("Sale record #{$sale->id} was deleted by {$user->name}.");

            DB::commit();

            return $this->success('Lead sale deleted successfully.');

        } catch (\Throwable $e) {
            DB::rollBack();

            return $this->error($e->getMessage(), 500);
        }
    }

    public function getAggregatedLeadSales(Request $request)
    {
        try {

            $user = $request->user();

            $hasRead = $user->can('report_management.sales.read');
            $hasOverride = $user->can('report_management.sales.override');

            if (!$hasRead && !$hasOverride) {
                return $this->error('Forbidden.', 403);
            }

            $accessibleUserIds = $this->accessibleUserIdsFor(
                $user,
                'report_management.sales.override'
            );

            $query = LeadSale::with([
                'creator',
                'assignee',
                'product',
                'lead',
            ])
                ->where('is_deleted', 0)
                ->where(function ($q) use ($accessibleUserIds) {
                    $q->whereIn('created_by', $accessibleUserIds)
                        ->orWhereIn('assigned_to', $accessibleUserIds);
                });

            if ($request->start_date) {
                $query->whereDate('sale_date', '>=', $request->start_date);
            }

            if ($request->end_date) {
                $query->whereDate('sale_date', '<=', $request->end_date);
            }

            if ($request->user_id) {
                $query->where(function ($q) use ($request) {
                    $q->where('created_by', $request->user_id)
                        ->orWhere('assigned_to', $request->user_id);
                });
            }

            $sales = $query->get();

            $aggregated = [];

            foreach ($sales as $sale) {

                $creatorId = $sale->created_by;
                $assigneeId = $sale->assigned_to;

                $users = [];

                if (!$assigneeId || $creatorId == $assigneeId) {

                    $users[] = [
                        'id' => $creatorId,
                        'share' => 1
                    ];

                } else {

                    $users[] = [
                        'id' => $creatorId,
                        'share' => 0.5
                    ];

                    $users[] = [
                        'id' => $assigneeId,
                        'share' => 0.5
                    ];
                }

                foreach ($users as $u) {

                    $uid = $u['id'];
                    $share = $u['share'];

                    if (!isset($aggregated[$uid])) {

                        $userModel = null;

                        if (
                            $sale->creator &&
                            $sale->creator->id == $uid
                        ) {
                            $userModel = $sale->creator;
                        }

                        if (
                            $sale->assignee &&
                            $sale->assignee->id == $uid
                        ) {
                            $userModel = $sale->assignee;
                        }

                        $aggregated[$uid] = [
                            'user' => [
                                'id' => $uid,
                                'name' => $userModel->name ?? 'Unknown',
                                'image' => $userModel?->image_path ? Storage::disk('public')->url($userModel->image_path) : null,
                            ],

                            'total_clients' => 0,
                            'client_ids' => [],
                            'total_sales' => 0,
                            'total_amount' => 0,
                            'total_incentive' => 0,

                            'first_sale_date' => $sale->sale_date,
                            'last_sale_date' => $sale->sale_date,
                        ];
                    }

                    if ($sale->lead_id) {

                        $aggregated[$uid]['client_ids'][] = $sale->lead_id;
                    }

                    $aggregated[$uid]['total_sales'] += 1;

                    $aggregated[$uid]['total_amount'] +=
                        $sale->total * $share;

                    $aggregated[$uid]['total_incentive'] +=
                        $sale->incentive * $share;

                    if (
                        $sale->sale_date <
                        $aggregated[$uid]['first_sale_date']
                    ) {
                        $aggregated[$uid]['first_sale_date'] =
                            $sale->sale_date;
                    }

                    if (
                        $sale->sale_date >
                        $aggregated[$uid]['last_sale_date']
                    ) {
                        $aggregated[$uid]['last_sale_date'] =
                            $sale->sale_date;
                    }
                }
            }

            $finalData = collect($aggregated)
                ->map(function ($data) {
                    $data['total_clients'] = count(array_unique($data['client_ids']));
                    unset($data['client_ids']);

                    return $data;
                })
                ->sortByDesc('total_amount')
                ->values();

            $page = $request->page ?? 1;
            $perPage = $request->per_page ?? 15;

            $totalItems = $finalData->count();

            $currentItems = $finalData
                ->slice(($page - 1) * $perPage, $perPage)
                ->values();

            $paginated = new LengthAwarePaginator(
                $currentItems,
                $totalItems,
                $perPage,
                $page,
                [
                    'path' => request()->url(),
                    'query' => request()->query(),
                ]
            );

            return $this->success(
                'Aggregated lead sales fetched successfully.',
                [
                    'data' => $currentItems,

                    'current_page' => $paginated->currentPage(),

                    'next_page' => $paginated->hasMorePages()
                        ? $paginated->currentPage() + 1
                        : null,

                    'last_page' => $paginated->lastPage(),

                    'total_items' => $paginated->total(),

                    'per_page' => $paginated->perPage(),
                ]
            );

        } catch (\Throwable $e) {

            return $this->error(
                $e->getMessage(),
                500
            );
        }
    }

    public function getIndividualLeadSales(Request $request)
    {
        try {

            $user = $request->user();

            $hasRead = $user->can('report_management.sales.read');
            $hasOverride = $user->can('report_management.sales.override');

            if (!$hasRead && !$hasOverride) {
                return $this->error('Forbidden.', 403);
            }

            $request->validate([
                'user_id' => ['required', 'exists:users,id'],
            ]);

            $query = LeadSale::with([
                'creator',
                'assignee',
                'product',
                'lead',
                'lead.company',
                'payment_type',
            ])
                ->where('is_deleted', 0)
                ->where('created_by', $request->user_id)
                ->orWhere('assigned_to', $request->user_id);

            // Date filters
            if ($request->start_date) {
                $query->whereDate('sale_date', '>=', $request->start_date);
            }

            if ($request->end_date) {
                $query->whereDate('sale_date', '<=', $request->end_date);
            }

            // Search filter
            if ($request->search) {

                $search = $request->search;

                $query->where(function ($q) use ($search) {

                    $q->whereHas('creator', function ($qq) use ($search) {
                        $qq->where('name', 'like', '%' . $search . '%');
                    })
                        ->orWhereHas('assignee', function ($qq) use ($search) {
                            $qq->where('name', 'like', '%' . $search . '%');
                        });

                });
            }

            $sales = $query
                ->orderBy('sale_date', 'desc')
                ->get();

            $formattedSales = $sales->map(function ($sale) {
                return $this->sale_data_format($sale);
            });

            $perPage = $request->per_page ?? 15;

            $currentPage = LengthAwarePaginator::resolveCurrentPage();

            $currentItems = $formattedSales
                ->slice(($currentPage - 1) * $perPage, $perPage)
                ->values();

            $paginated = new LengthAwarePaginator(
                $currentItems,
                $formattedSales->count(),
                $perPage,
                $currentPage,
                [
                    'path' => request()->url(),
                    'query' => request()->query(),
                ]
            );

            return $this->success(
                'Individual lead sales fetched successfully.',
                [
                    'data' => $currentItems,

                    'current_page' => $paginated->currentPage(),

                    'next_page' => $paginated->hasMorePages()
                        ? $paginated->currentPage() + 1
                        : null,

                    'last_page' => $paginated->lastPage(),

                    'total_items' => $paginated->total(),

                    'per_page' => $paginated->perPage(),
                ]
            );

        } catch (\Throwable $e) {

            return $this->error(
                $e->getMessage(),
                500
            );
        }
    }
}
