<?php
namespace App\Http\Controllers\Warehouse\FixedAssets;

use App\Http\Controllers\Controller;
use App\Models\Warehouse\FixedAssets\FixedAssetDepreciation;
use App\Models\Warehouse\FixedAssets\FixedAsset;
use App\Models\Warehouse\FixedAssets\FixedAssetCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class FixedAssetDepreciationController extends Controller
{
    public function __construct()
    {
        $this->middleware('warehouse.access');
        $this->middleware('warehouse.permission:warehouse.fixed-asset-depreciation.view')->only(['index', 'show', 'export']);
        $this->middleware('warehouse.permission:warehouse.fixed-asset-depreciation.calculate')->only(['calculate']);
    }

    public function index(Request $request)
    {
        $year = $request->input('year', now()->year);
        $month = $request->input('month', now()->month);

        $periodRecords = FixedAssetDepreciation::with(['fixedAsset.category', 'calculatedBy'])
            ->forYear($year)
            ->orderBy('depreciation_month')
            ->get();

        $assetQuery = FixedAsset::with('category')
            ->where('status', 'active')
            ->whereNotIn('lifecycle_status', ['disposed', 'retired'])
            ->orderBy('asset_code');

        if ($request->filled('category_id')) {
            $assetQuery->where('category_id', $request->category_id);
        }

        $records = $assetQuery->paginate(25)->withQueryString();

        $summaryAssets = (clone $assetQuery)->reorder()->get();

        $summary = [
            'total_assets' => $summaryAssets->count(),
            'total_purchase_value' => $summaryAssets->sum('purchase_price'),
            'total_accumulated_depreciation' => $summaryAssets->sum(fn ($asset) => max(0, ($asset->purchase_price ?? 0) - ($asset->current_book_value ?? 0))),
            'total_book_value' => $summaryAssets->sum('current_book_value'),
            'period_depreciation' => $periodRecords->sum('depreciation_amount'),
            'period_assets_count' => $periodRecords->pluck('fixed_asset_id')->unique()->count(),
        ];

        $categories = FixedAssetCategory::where('status', 'active')->orderBy('category_name')->get();

        return view('warehouse.fixed-assets.depreciation.index', compact('records', 'year', 'month', 'summary', 'categories'));
    }

    public function show($assetId)
    {
        $asset = FixedAsset::with(['category', 'supplier'])->findOrFail($assetId);
        $records = FixedAssetDepreciation::where('fixed_asset_id', $assetId)
            ->orderBy('depreciation_year')
            ->orderBy('depreciation_month')
            ->get();

        return view('warehouse.fixed-assets.depreciation.show', compact('asset', 'records'));
    }

    public function calculate(Request $request)
    {
        $request->validate([
            'year' => 'required|integer|min:2000|max:2100',
            'month' => 'required|integer|min:1|max:12',
        ]);

        $year = $request->year;
        $month = $request->month;

        DB::beginTransaction();
        try {
            $assets = FixedAsset::where('status', 'active')
                ->whereNotNull('depreciation_method')
                ->where('depreciation_method', '!=', 'none')
                ->whereNotIn('lifecycle_status', ['disposed', 'retired'])
                ->get();

            $calculated = 0;
            $skipped = 0;

            foreach ($assets as $asset) {
                // Skip if already calculated for this period
                $exists = FixedAssetDepreciation::where('fixed_asset_id', $asset->id)
                    ->forPeriod($year, $month)
                    ->exists();

                if ($exists) {
                    $skipped++;
                    continue;
                }

                // Get last depreciation record for opening book value
                $lastRecord = FixedAssetDepreciation::where('fixed_asset_id', $asset->id)
                    ->orderBy('depreciation_year', 'desc')
                    ->orderBy('depreciation_month', 'desc')
                    ->first();

                $openingBookValue = $lastRecord ? $lastRecord->closing_book_value : $asset->purchase_price;
                $accumulatedDepreciation = $lastRecord ? $lastRecord->accumulated_depreciation : 0;

                if ($openingBookValue <= ($asset->salvage_value ?? 0)) {
                    $skipped++;
                    continue;
                }

                // Calculate depreciation
                $depreciationAmount = 0;
                $usefulLifeYears = $asset->useful_life_years ?? 5;
                $salvageValue = $asset->salvage_value ?? 0;

                if ($asset->depreciation_method === 'straight_line') {
                    $depreciationAmount = round(($asset->purchase_price - $salvageValue) / ($usefulLifeYears * 12), 2);
                } elseif ($asset->depreciation_method === 'declining_balance') {
                    $rate = 2 / $usefulLifeYears;
                    $depreciationAmount = round($rate * $openingBookValue / 12, 2);
                }

                // Don't depreciate below salvage value
                $maxDepreciation = $openingBookValue - $salvageValue;
                $depreciationAmount = min($depreciationAmount, $maxDepreciation);
                $depreciationAmount = max($depreciationAmount, 0);

                $closingBookValue = $openingBookValue - $depreciationAmount;
                $newAccumulated = $accumulatedDepreciation + $depreciationAmount;

                FixedAssetDepreciation::create([
                    'fixed_asset_id' => $asset->id,
                    'depreciation_year' => $year,
                    'depreciation_month' => $month,
                    'opening_book_value' => $openingBookValue,
                    'depreciation_amount' => $depreciationAmount,
                    'accumulated_depreciation' => $newAccumulated,
                    'closing_book_value' => $closingBookValue,
                    'depreciation_method' => $asset->depreciation_method,
                    'useful_life_years' => $usefulLifeYears,
                    'salvage_value' => $salvageValue,
                    'calculated_by' => Auth::id(),
                    'calculated_at' => now(),
                ]);

                // Update asset's current book value
                $asset->update(['current_book_value' => $closingBookValue]);

                $calculated++;
            }

            DB::commit();

            $message = "Depreciation calculated for {$calculated} asset(s). {$skipped} skipped.";

            if ($request->expectsJson()) {
                return response()->json(['success' => true, 'message' => $message, 'calculated' => $calculated, 'skipped' => $skipped]);
            }
            return redirect()->route('warehouse.fixed-assets.depreciation.index', ['year' => $year, 'month' => $month])
                ->with('success', $message);
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::error('FixedAssetDepreciationController@calculate error: ' . $e->getMessage());
            if ($request->expectsJson()) {
                return response()->json(['success' => false, 'message' => $e->getMessage()], 400);
            }
            return back()->with('error', $e->getMessage());
        }
    }

    public function export(Request $request)
    {
        $year = $request->input('year', now()->year);

        try {
            $records = FixedAssetDepreciation::with(['fixedAsset.category'])
                ->forYear($year)
                ->orderBy('depreciation_month')
                ->get();

            $spreadsheet = new Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();
            $sheet->setTitle('Depreciation ' . $year);

            $headers = ['Asset Code', 'Asset Name', 'Category', 'Year', 'Month', 'Opening Book Value', 'Depreciation Amount', 'Accumulated Depreciation', 'Closing Book Value', 'Method'];
            foreach ($headers as $i => $header) {
                $col = chr(65 + $i);
                $sheet->setCellValue($col . '1', $header);
                $sheet->getStyle($col . '1')->getFont()->setBold(true);
            }

            $row = 2;
            foreach ($records as $record) {
                $sheet->setCellValue('A' . $row, $record->fixedAsset->asset_code ?? '-');
                $sheet->setCellValue('B' . $row, $record->fixedAsset->asset_name ?? '-');
                $sheet->setCellValue('C' . $row, $record->fixedAsset->category->category_name ?? '-');
                $sheet->setCellValue('D' . $row, $record->depreciation_year);
                $sheet->setCellValue('E' . $row, $record->depreciation_month);
                $sheet->setCellValue('F' . $row, $record->opening_book_value);
                $sheet->setCellValue('G' . $row, $record->depreciation_amount);
                $sheet->setCellValue('H' . $row, $record->accumulated_depreciation);
                $sheet->setCellValue('I' . $row, $record->closing_book_value);
                $sheet->setCellValue('J' . $row, ucfirst(str_replace('_', ' ', $record->depreciation_method)));
                $row++;
            }

            foreach (range('A', 'J') as $col) { $sheet->getColumnDimension($col)->setAutoSize(true); }

            $tempDir = storage_path('app/temp');
            if (!file_exists($tempDir)) mkdir($tempDir, 0755, true);
            $fileName = 'depreciation_' . $year . '_' . date('Ymd_His') . '.xlsx';
            $filePath = $tempDir . '/' . $fileName;
            $writer = new Xlsx($spreadsheet);
            $writer->save($filePath);

            return response()->download($filePath, $fileName)->deleteFileAfterSend(true);
        } catch (\Exception $e) {
            \Log::error('FixedAssetDepreciationController@export error: ' . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 400);
        }
    }
}
