<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Storage;

class UnitController extends Controller
{
    // GET /api/units
    public function index(Request $request)
    {
        $user = Auth::user();
        if (!$user) {
            return response()->json(['status' => 'error', 'message' => 'Unauthenticated'], 401);
        }
        if (!$user->society_id) {
            return response()->json(['status' => 'error', 'message' => 'User not associated with a society'], 403);
        }

        // Stats Logic
        $stats = [
            'total' => DB::table('units')->where('society_id', $user->society_id)->count(),
            'occupied' => DB::table('units')->where('society_id', $user->society_id)->where('status', 'occupied')->count(),
            'vacant' => DB::table('units')->where('society_id', $user->society_id)->where('status', 'vacant')->count(),
        ];

        $query = DB::table('units')
            ->where('units.society_id', $user->society_id)
            ->leftJoin('member_units', 'units.id', '=', 'member_units.unit_id')
            ->leftJoin('users', 'member_units.user_id', '=', 'users.id')
            ->select(
                'units.*',
                'users.name as member_name',
                'member_units.ownership_type'
            );

        if ($request->has('search') && $request->search != '') {
            $search = $request->search;
            $query->where('units.unit_number', 'like', "%{$search}%");
        }

        if ($request->has('status') && $request->status != '') {
            $query->where('units.status', $request->status);
        }

        // Sorting
        $sortColumn = $request->get('sort_by', 'unit_number'); // Default sort
        $sortOrder = $request->get('sort_order', 'asc');

        // Allowed sort columns to prevent SQL injection or errors
        $allowedSorts = ['unit_number', 'unit_type', 'status', 'monthly_maintenance'];
        if (in_array($sortColumn, $allowedSorts)) {
            $query->orderBy('units.' . $sortColumn, $sortOrder);
        } else {
            $query->orderBy('units.unit_number', 'asc');
        }

        $units = $query->paginate(10);

        return response()->json([
            'status' => 'success',
            'data' => $units,
            'stats' => $stats
        ]);
    }

    // POST /api/units
    public function store(Request $request)
    {
        $user = Auth::user();
        if (!$user || !$user->society_id) {
            return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403);
        }

        $validator = Validator::make($request->all(), [
            'unit_number' => 'required|string|max:50',
            'wing' => 'nullable|string|max:50',
            'floor' => 'nullable|integer',
            'unit_type' => 'required|in:flat,shop,office',
            'area_sqft' => 'nullable|numeric',
            'monthly_maintenance' => 'required|numeric|min:0',
        ]);

        if ($validator->fails()) {
            return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);
        }

        // Check for duplicate unit number in same society
        $exists = DB::table('units')
            ->where('society_id', $user->society_id)
            ->where('unit_number', $request->unit_number)
            ->exists();

        if ($exists) {
            return response()->json(['status' => 'error', 'message' => 'Unit number already exists in this society'], 422);
        }

        $id = DB::table('units')->insertGetId([
            'society_id' => $user->society_id,
            'unit_number' => $request->unit_number,
            'wing' => $request->wing,
            'floor' => $request->floor,
            'unit_type' => $request->unit_type,
            'area_sqft' => $request->area_sqft,
            'monthly_maintenance' => $request->monthly_maintenance,
            'status' => 'vacant',
            'created_at' => now(),
            'updated_at' => now()
        ]);

        return response()->json(['status' => 'success', 'message' => 'Unit created successfully', 'id' => $id], 201);
    }

    // PUT /api/units/{id}
    public function update(Request $request, $id)
    {
        $user = Auth::user();
        if (!$user || !$user->society_id) {
            return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403);
        }

        $validator = Validator::make($request->all(), [
            'unit_number' => 'sometimes|required|string|max:50',
            'wing' => 'nullable|string|max:50',
            'floor' => 'nullable|integer',
            'unit_type' => 'sometimes|required|in:flat,shop,office',
            'area_sqft' => 'nullable|numeric',
            'monthly_maintenance' => 'sometimes|required|numeric|min:0',
            'status' => 'sometimes|required|in:occupied,vacant'
        ]);

        if ($validator->fails()) {
            return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);
        }

        $updated = DB::table('units')
            ->where('id', $id)
            ->where('society_id', $user->society_id)
            ->update(array_merge($request->only([
                'unit_number',
                'wing',
                'floor',
                'unit_type',
                'area_sqft',
                'monthly_maintenance',
                'status'
            ]), ['updated_at' => now()]));

        if (!$updated) {
            return response()->json(['status' => 'error', 'message' => 'Unit not found or unauthorized'], 404);
        }

        return response()->json(['status' => 'success', 'message' => 'Unit updated successfully']);
    }

    // POST /api/units/{id}/assign-member
    public function assignMember(Request $request, $id)
    {
        $user = Auth::user();
        if (!$user || !$user->society_id) {
            return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403);
        }

        $validator = Validator::make($request->all(), [
            'user_id' => 'required|exists:users,id',
            'ownership_type' => 'required|in:owner,tenant',
            'move_in_date' => 'nullable|date'
        ]);

        if ($validator->fails()) {
            return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);
        }

        // Verify unit belongs to this society
        $unit = DB::table('units')->where('id', $id)->where('society_id', $user->society_id)->first();
        if (!$unit) {
            return response()->json(['status' => 'error', 'message' => 'Unit not found'], 404);
        }

        // Insert member-unit mapping
        DB::table('member_units')->insert([
            'user_id' => $request->user_id,
            'unit_id' => $id,
            'ownership_type' => $request->ownership_type,
            'move_in_date' => $request->move_in_date ?? now(),
            'created_at' => now(),
            'updated_at' => now()
        ]);

        // Update unit status to occupied
        DB::table('units')->where('id', $id)->update(['status' => 'occupied', 'updated_at' => now()]);

        // Handle File Upload
        $docs = [];
        if ($request->hasFile('document')) {
            $path = $request->file('document')->store('unit_documents', 'public');
            $docs[] = $path;
        }

        // --- Log History (Occupied) ---
        // Close any open vacant log
        DB::table('unit_occupancy_logs')
            ->where('unit_id', $id)
            ->where('status', 'vacant')
            ->whereNull('end_date')
            ->update(['end_date' => now(), 'updated_at' => now()]);

        // Create Occupied Log
        $residentName = DB::table('users')->where('id', $request->user_id)->value('name');
        DB::table('unit_occupancy_logs')->insert([
            'unit_id' => $id,
            'resident_name' => $residentName,
            'status' => 'occupied',
            'start_date' => $request->move_in_date ?? now(),
            'documents' => json_encode($docs),
            'created_at' => now(),
            'updated_at' => now()
        ]);

        return response()->json(['status' => 'success', 'message' => 'Member assigned to unit successfully']);
    }

    // POST /api/units/{id}/vacate
    public function vacate(Request $request, $id)
    {
        $user = Auth::user();
        if (!$user || !$user->society_id) {
            return response()->json(['status' => 'error', 'message' => 'Unauthorized'], 403);
        }

        $unit = DB::table('units')->where('id', $id)->where('society_id', $user->society_id)->first();
        if (!$unit) {
            return response()->json(['status' => 'error', 'message' => 'Unit not found'], 404);
        }

        // Remove association (Assuming we don't keep history in this table for now, or we rely on logs)
        // Ideally we would set move_out_date if the schema supported it, but simpler to delete to clear the 'active' member.
        DB::table('member_units')->where('unit_id', $id)->delete();

        // Update status
        DB::table('units')->where('id', $id)->update(['status' => 'vacant', 'updated_at' => now()]);

        // --- Log History (Vacant) ---
        // Close any open occupied log
        DB::table('unit_occupancy_logs')
            ->where('unit_id', $id)
            ->where('status', 'occupied')
            ->whereNull('end_date')
            ->update(['end_date' => now(), 'updated_at' => now()]);

        // Create Vacant Log
        DB::table('unit_occupancy_logs')->insert([
            'unit_id' => $id,
            'resident_name' => null,
            'status' => 'vacant',
            'start_date' => now(),
            'documents' => json_encode([]),
            'created_at' => now(),
            'updated_at' => now()
        ]);

        return response()->json(['status' => 'success', 'message' => 'Unit vacated successfully']);
    }

    // GET /api/units/{id}/history
    public function getHistory($id)
    {
        $user = Auth::user();
        if (!$user || !$user->society_id)
            return response()->json(['status' => 'error'], 403);

        $logs = DB::table('unit_occupancy_logs')
            ->where('unit_id', $id)
            ->orderBy('start_date', 'desc')
            ->get();

        // Decode documents
        foreach ($logs as $log) {
            $log->documents = $log->documents ? json_decode($log->documents) : [];
        }

        return response()->json(['status' => 'success', 'data' => $logs]);
    }

    // POST /api/units/{id}/history (Manual Log)
    public function addHistoryLog(Request $request, $id)
    {
        $validator = Validator::make($request->all(), [
            'status' => 'required|in:occupied,vacant',
            'resident_name' => 'nullable|string',
            'start_date' => 'required|date',
            'end_date' => 'nullable|date'
        ]);

        if ($validator->fails())
            return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);

        DB::table('unit_occupancy_logs')->insert([
            'unit_id' => $id,
            'resident_name' => $request->resident_name,
            'status' => $request->status,
            'start_date' => $request->start_date,
            'end_date' => $request->end_date,
            'documents' => json_encode([]),
            'created_at' => now(),
            'updated_at' => now()
        ]);

        return response()->json(['status' => 'success', 'message' => 'History log added']);
    }

    // POST /api/units/history/{logId}/upload
    public function uploadHistoryDocument(Request $request, $logId)
    {
        if (!$request->hasFile('document'))
            return response()->json(['status' => 'error', 'message' => 'No file'], 400);

        $path = $request->file('document')->store('unit_documents', 'public');

        $log = DB::table('unit_occupancy_logs')->where('id', $logId)->first();
        if (!$log)
            return response()->json(['status' => 'error', 'message' => 'Log not found'], 404);

        $docs = $log->documents ? json_decode($log->documents, true) : [];
        $docs[] = $path;

        DB::table('unit_occupancy_logs')->where('id', $logId)->update(['documents' => json_encode($docs)]);

        return response()->json(['status' => 'success', 'message' => 'Document uploaded', 'path' => $path]);
    }

    // GET /api/units/history/download/{filename}
    public function downloadHistoryDocument($filename)
    {
        $path = 'unit_documents/' . $filename;
        if (!Storage::disk('public')->exists($path)) {
            return response()->json(['message' => 'File not found'], 404);
        }
        return Storage::disk('public')->download($path);
    }
}
