<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\SubcontractorContactPerson;
use App\Models\SubcontractorCompany;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\QueryException;

class SubContractorController extends Controller
{
    /**
     * Display a listing of subcontractors.
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $ids = $this->getCustomerAndWorkspaceIds();
        if (!$ids) {
            return $this->withCount(collect([]), 'Subcontractors retrieved successfully');
        }

        // Join with subcontractor_companies to filter by customer and workspace
        $query = User::where('users.user_type', 5)
            ->where('users.del', '0')
            ->join('subcontractor_companies', 'users.id', '=', 'subcontractor_companies.user_id')
            ->where('subcontractor_companies.customer_id', $ids['customer_id'])
            ->where('subcontractor_companies.workspace_id', $ids['workspace_id'])
            ->where('subcontractor_companies.del', '0')
            ->with('contactPersons')
            ->select('users.*')
            ->latest('users.id');
        
        // Apply search filters
        if ($request->filled('search')) {
            $searchTerm = $request->search;
            $query->where(function ($q) use ($searchTerm) {
                $q->where('users.name', 'like', '%' . $searchTerm . '%')
                  ->orWhere('users.company_name', 'like', '%' . $searchTerm . '%')
                  ->orWhere('users.email', 'like', '%' . $searchTerm . '%')
                  ->orWhere('users.mobile_number', 'like', '%' . $searchTerm . '%')
                  ->orWhere('users.abn', 'like', '%' . $searchTerm . '%')
                  ->orWhereHas('contactPersons', function ($subquery) use ($searchTerm) {
                      $subquery->where('name', 'like', '%' . $searchTerm . '%');
                  });
            });
        }
        
        // Filter by trade_id (from subcontractor_companies)
        if ($request->filled('trade_id')) {
            $query->where('subcontractor_companies.trade_id', $request->input('trade_id'));
        }
        
        $subcontractors = $query->get()->map(function($subcontractor) use ($ids) {
            if ($subcontractor->company_logo) {
                $subcontractor->company_logo_url = url($subcontractor->company_logo);
            } else {
                $subcontractor->company_logo_url = null;
            }
            
            // Add project_ids and trade_id from subcontractor_companies
            $subcontractorCompany = SubcontractorCompany::where('user_id', $subcontractor->id)
                ->where('customer_id', $ids['customer_id'])
                ->where('workspace_id', $ids['workspace_id'])
                ->where('del', '0')
                ->first();
            
            if ($subcontractorCompany) {
                $subcontractor->project_ids = $subcontractorCompany->project_ids ?? [];
                $subcontractor->trade_id = $subcontractorCompany->trade_id;
            } else {
                $subcontractor->project_ids = [];
                $subcontractor->trade_id = null;
            }
            
            return $subcontractor;
        });
        
        return $this->withCount($subcontractors, 'Subcontractors retrieved successfully');
    }

    /**
     * Store a newly created subcontractor in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'company_name' => 'required|string|max:255',
            'abn' => 'nullable|string|max:20',
            'company_logo' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg,webp|max:2048',
            'trade_id' => 'nullable|integer',
            'company_number' => 'nullable|string|max:255',
            'name' => 'required|string|max:255',
            'mobile_number' => 'required|string|max:20',
            'email' => 'nullable|email|max:255',
            'project_ids' => 'nullable|array',
            'project_ids.*' => 'integer',
            'contact_persons' => 'nullable|array',
            'contact_persons.*.name' => 'required|string|max:255',
            'contact_persons.*.email' => 'nullable|email|max:255',
            'contact_persons.*.phone' => 'nullable|string|max:20',
            'contact_persons.*.role' => 'nullable|string|max:255',
        ], [
            'company_name.required' => 'Company name is required',
            'name.required' => 'Owner name is required',
            'mobile_number.required' => 'Contact number is required',
            'email.unique' => 'Email already exists',
            'company_logo.image' => 'Company logo must be an image',
            'company_logo.mimes' => 'Company logo must be jpeg, png, jpg, gif, svg or webp',
            'company_logo.max' => 'Company logo must not exceed 2MB',
            'contact_persons.*.name.required' => 'Name is required for all contact persons',
            'contact_persons.*.email.email' => 'Email must be a valid email address',
        ]);

        if ($validator->fails()) {
            return $this->error($validator->errors()->first(), 422);
        }

        try {
            $ids = $this->getCustomerAndWorkspaceIds();
            
            // Check if a user with the same email and user_type 5 already exists
            $existingSubcontractor = null;
            if ($request->filled('email')) {
                $existingSubcontractor = User::where('email', $request->email)
                    ->where('user_type', 5)
                    ->where('del', '0')
                    ->first();
            }

            // If user exists, use it; otherwise create a new user
            if ($existingSubcontractor) {
                $subcontractor = $existingSubcontractor;
                
                // Check if this customer already has this subcontractor
                $existingCompany = SubcontractorCompany::where('user_id', $subcontractor->id)
                    ->where('customer_id', $ids['customer_id'])
                    ->where('workspace_id', $ids['workspace_id'])
                    ->where('del', '0')
                    ->first();
                
                if ($existingCompany) {
                    return $this->error('This subcontractor is already associated with your company', 422);
                }
            } else {
                // Handle company logo upload
                $companyLogoPath = null;
                if ($request->hasFile('company_logo')) {
                    $companyLogoPath = $this->handleFileImageUpload($request, 'SubContractors')['path'] ?? null;
                }

                $subcontractor = User::create([
                    'name' => $request->name,
                    'email' => $request->email,
                    'mobile_number' => $request->mobile_number,
                    'company_name' => $request->company_name,
                    'abn' => $request->abn,
                    'company_logo' => $companyLogoPath,
                    'company_number' => $request->company_number,
                    'user_type' => 5, // Subcontractor user type
                    'active_status' => 1,
                    'is_enable_login' => 1,
                    'del' => '0',
                    'created_by' => Auth::id(),
                    'current_company' => $ids['customer_id'] ?? null,
                    'current_company_workspace' => $ids['workspace_id'] ?? null,
                ]);

                if (!$subcontractor) {
                    return $this->message('Failed to create subcontractor.', 500);
                }
            }

            // Create entry in subcontractor_companies table
            $subcontractorCompany = SubcontractorCompany::create([
                'user_id' => $subcontractor->id,
                'customer_id' => $ids['customer_id'] ?? null,
                'workspace_id' => $ids['workspace_id'] ?? null,
                'trade_id' => $request->trade_id,
                'project_ids' => $request->project_ids ?? [],
                'del' => '0',
            ]);

            // Only set current_company and current_company_workspace for NEW subcontractors
            // If subcontractor already exists (added by another customer), don't update these fields
            // They should only be set when the user is first created
            // Note: current_company and current_company_workspace are already set in User::create() above for new users

            if (!$subcontractorCompany) {
                return $this->message('Failed to create subcontractor company association.', 500);
            }

            // Save contact persons if provided
            if (isset($request->contact_persons) && is_array($request->contact_persons)) {
                foreach ($request->contact_persons as $contactPerson) {
                    SubcontractorContactPerson::create([
                        'subcontractor_id' => $subcontractor->id,
                        'name' => $contactPerson['name'],
                        'email' => $contactPerson['email'] ?? null,
                        'phone' => $contactPerson['phone'] ?? null,
                        'role' => $contactPerson['role'] ?? null,
                        'customer_id' => $ids['customer_id'] ?? null,
                        'workspace_id' => $ids['workspace_id'] ?? null,
                        'del' => '0',
                    ]);
                }
            }

            // Add logo URL to response
            if ($subcontractor->company_logo) {
                $subcontractor->company_logo_url = url($subcontractor->company_logo);
            } else {
                $subcontractor->company_logo_url = null;
            }

            // Add project_ids to response
            $subcontractor->project_ids = $subcontractorCompany->project_ids ?? [];

            // Load contact persons for response
            $subcontractor->load('contactPersons');

            return $this->success($subcontractor, 'Subcontractor created successfully');
        } catch (QueryException $exception) {
            preg_match("/'([^']+)'/", $exception->getMessage(), $matches);
            $errorField = $matches[1] ?? 'unknown';
            return $this->message('The ' . $errorField . ' field is required.', 400);
        }
    }

    /**
     * Display the specified subcontractor.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $ids = $this->getCustomerAndWorkspaceIds();
        if (!$ids) {
            return $this->message('Subcontractor not found', 404);
        }

        // Join with subcontractor_companies to filter by customer and workspace
        $subcontractor = User::where('users.user_type', 5)
            ->where('users.del', '0')
            ->where('users.id', $id)
            ->join('subcontractor_companies', 'users.id', '=', 'subcontractor_companies.user_id')
            ->where('subcontractor_companies.customer_id', $ids['customer_id'])
            ->where('subcontractor_companies.workspace_id', $ids['workspace_id'])
            ->where('subcontractor_companies.del', '0')
            ->with('contactPersons')
            ->select('users.*')
            ->first();

        if (!$subcontractor) {
            return $this->message('Subcontractor not found', 404);
        }

        // Add logo URL
        if ($subcontractor->company_logo) {
            $subcontractor->company_logo_url = url($subcontractor->company_logo);
        } else {
            $subcontractor->company_logo_url = null;
        }

        // Add project_ids and trade_id from subcontractor_companies
        $subcontractorCompany = SubcontractorCompany::where('user_id', $subcontractor->id)
            ->where('customer_id', $ids['customer_id'])
            ->where('workspace_id', $ids['workspace_id'])
            ->where('del', '0')
            ->first();
        
        if ($subcontractorCompany) {
            $subcontractor->project_ids = $subcontractorCompany->project_ids ?? [];
            $subcontractor->trade_id = $subcontractorCompany->trade_id;
        } else {
            $subcontractor->project_ids = [];
            $subcontractor->trade_id = null;
        }

        return $this->success($subcontractor, 'Subcontractor retrieved successfully');
    }

    /**
     * Update the specified subcontractor in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $ids = $this->getCustomerAndWorkspaceIds();
        if (!$ids) {
            return $this->message('Subcontractor not found', 404);
        }

        // Check if subcontractor exists and is associated with this customer/workspace
        $subcontractor = User::where('user_type', 5)
            ->where('del', '0')
            ->find($id);

        if (!$subcontractor) {
            return $this->message('Subcontractor not found', 404);
        }

        // Check authorization via subcontractor_companies
        $subcontractorCompany = SubcontractorCompany::where('user_id', $id)
            ->where('customer_id', $ids['customer_id'])
            ->where('workspace_id', $ids['workspace_id'])
            ->where('del', '0')
            ->first();

        if (!$subcontractorCompany) {
            return $this->message('You do not have access to this subcontractor', 403);
        }

        $validator = Validator::make($request->all(), [
            'company_name' => 'required|string|max:255',
            'abn' => 'nullable|string|max:20',
            'company_logo' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg,webp|max:2048',
            'trade_id' => 'nullable|integer',
            'company_number' => 'nullable|string|max:255',
            'name' => 'required|string|max:255',
            'mobile_number' => 'required|string|max:20',
            'email' => 'nullable|email|max:255|unique:users,email,' . $id,
            'project_ids' => 'nullable|array',
            'project_ids.*' => 'integer',
            'contact_persons' => 'nullable|array',
            'contact_persons.*.name' => 'required|string|max:255',
            'contact_persons.*.email' => 'nullable|email|max:255',
            'contact_persons.*.phone' => 'nullable|string|max:20',
            'contact_persons.*.role' => 'nullable|string|max:255',
        ], [
            'company_name.required' => 'Company name is required',
            'name.required' => 'Owner name is required',
            'mobile_number.required' => 'Contact number is required',
            'email.unique' => 'Email already exists',
            'company_logo.image' => 'Company logo must be an image',
            'company_logo.mimes' => 'Company logo must be jpeg, png, jpg, gif, svg or webp',
            'company_logo.max' => 'Company logo must not exceed 2MB',
            'contact_persons.*.name.required' => 'Name is required for all contact persons',
            'contact_persons.*.email.email' => 'Email must be a valid email address',
        ]);

        if ($validator->fails()) {
            return $this->error($validator->errors()->first(), 422);
        }

        try {
            // Handle company logo upload and retain the existing image if not updated
            $currentLogo = $subcontractor->company_logo;
            $companyLogoPath = $this->handleFileImageUpload($request, 'SubContractors', $currentLogo)['path'] ?? $currentLogo;

            $subcontractor->update([
                'name' => $request->name,
                'email' => $request->email,
                'mobile_number' => $request->mobile_number,
                'company_name' => $request->company_name,
                'abn' => $request->abn,
                'company_logo' => $companyLogoPath,
                'company_number' => $request->company_number,
            ]);

            // Update subcontractor_companies entry
            $subcontractorCompany->update([
                'trade_id' => $request->trade_id,
                'project_ids' => $request->project_ids ?? [],
            ]);

            // Update current_company and current_company_workspace if provided
            if ($request->filled('current_company')) {
                // Verify that the current_company is a valid customer association
                $validCompany = SubcontractorCompany::where('user_id', $subcontractor->id)
                    ->where('customer_id', $request->current_company)
                    ->where('del', '0')
                    ->first();
                
                if ($validCompany) {
                    $subcontractor->update([
                        'current_company' => $request->current_company,
                        'current_company_workspace' => $validCompany->workspace_id,
                    ]);
                }
            }

            // Update contact persons if provided
            if (isset($request->contact_persons) && is_array($request->contact_persons)) {
                // Delete existing contact persons (like CompanyController)
                $subcontractor->contactPersons()->delete();
                
                // Create new contact persons
                $ids = $this->getCustomerAndWorkspaceIds();
                foreach ($request->contact_persons as $contactPerson) {
                    SubcontractorContactPerson::create([
                        'subcontractor_id' => $id,
                        'name' => $contactPerson['name'],
                        'email' => $contactPerson['email'] ?? null,
                        'phone' => $contactPerson['phone'] ?? null,
                        'role' => $contactPerson['role'] ?? null,
                        'customer_id' => $ids['customer_id'] ?? null,
                        'workspace_id' => $ids['workspace_id'] ?? null,
                        'del' => '0',
                    ]);
                }
            }

            // Add logo URL to response
            if ($subcontractor->company_logo) {
                $subcontractor->company_logo_url = url($subcontractor->company_logo);
            } else {
                $subcontractor->company_logo_url = null;
            }

            // Add project_ids and trade_id to response
            $subcontractor->project_ids = $subcontractorCompany->project_ids ?? [];
            $subcontractor->trade_id = $subcontractorCompany->trade_id;

            // Load contact persons for response
            $subcontractor->load('contactPersons');

            return $this->success($subcontractor, 'Subcontractor updated successfully');
        } catch (QueryException $exception) {
            preg_match("/'([^']+)'/", $exception->getMessage(), $matches);
            $errorField = $matches[1] ?? 'unknown';
            return $this->message('The ' . $errorField . ' field is required.', 400);
        }
    }

    /**
     * Remove the specified subcontractor from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $ids = $this->getCustomerAndWorkspaceIds();
        if (!$ids) {
            return $this->message('Subcontractor not found', 404);
        }

        $subcontractor = User::where('user_type', 5)
            ->where('del', '0')
            ->find($id);

        if (!$subcontractor) {
            return $this->message('Subcontractor not found', 404);
        }

        // Check authorization via subcontractor_companies
        $subcontractorCompany = SubcontractorCompany::where('user_id', $id)
            ->where('customer_id', $ids['customer_id'])
            ->where('workspace_id', $ids['workspace_id'])
            ->where('del', '0')
            ->first();

        if (!$subcontractorCompany) {
            return $this->message('You do not have access to this subcontractor', 403);
        }

        // Soft delete the subcontractor_companies entry (not the user itself)
        $subcontractorCompany->update(['del' => '1']);

        return $this->message('Subcontractor deleted successfully');
    }

    /**
     * Get all companies (customers) the authenticated subcontractor is associated with.
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function getAssociatedCompanies(Request $request)
    {
        $subcontractor = Auth::guard('admin')->user();
        
        if (!$subcontractor || $subcontractor->user_type != 5) {
            return $this->error('Unauthorized. Only subcontractors can access this endpoint.', 403);
        }

        // Get all companies (customers) this subcontractor is associated with
        $subcontractorCompanies = SubcontractorCompany::where('user_id', $subcontractor->id)
            ->where('del', '0')
            ->get();

        $companies = [];
        foreach ($subcontractorCompanies as $subcontractorCompany) {
            $customer = User::find($subcontractorCompany->customer_id);
            if ($customer) {
                $companies[] = [
                    'id' => $customer->id,
                    'name' => $customer->name,
                    'email' => $customer->email,
                    'current_workspace_id' => $customer->current_workspace_id,
                    'workspace_id' => $subcontractorCompany->workspace_id, // The workspace this subcontractor is associated with for this customer
                    'is_current_company' => ($subcontractor->current_company == $customer->id && 
                                           $subcontractor->current_company_workspace == $subcontractorCompany->workspace_id),
                ];
            }
        }

        return $this->success($companies, 'Associated companies retrieved successfully');
    }

    /**
     * Update the current company and current_company_workspace for the authenticated subcontractor.
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function updateCurrentCompany(Request $request)
    {
        $subcontractor = Auth::guard('admin')->user();
        
        if (!$subcontractor || $subcontractor->user_type != 5) {
            return $this->error('Unauthorized. Only subcontractors can access this endpoint.', 403);
        }

        $validator = Validator::make($request->all(), [
            'current_company' => 'required|integer|exists:users,id',
            'current_company_workspace' => 'required|integer',
        ], [
            'current_company.required' => 'Current company is required',
            'current_company.integer' => 'Current company must be a valid ID',
            'current_company.exists' => 'The selected company does not exist',
            'current_company_workspace.required' => 'Current company workspace is required',
            'current_company_workspace.integer' => 'Current company workspace must be a valid ID',
        ]);

        if ($validator->fails()) {
            return $this->error($validator->errors()->first(), 422);
        }

        // Verify that the subcontractor is associated with this company and workspace
        $subcontractorCompany = SubcontractorCompany::where('user_id', $subcontractor->id)
            ->where('customer_id', $request->current_company)
            ->where('workspace_id', $request->current_company_workspace)
            ->where('del', '0')
            ->first();

        if (!$subcontractorCompany) {
            return $this->error('You are not associated with this company and workspace combination.', 403);
        }

        // Verify that the customer exists and is a valid customer (user_type should be customer)
        $customer = User::find($request->current_company);
        if (!$customer || $customer->user_type != config('constants.user_types.customer')) {
            return $this->error('Invalid company. The selected company is not a valid customer.', 422);
        }

        // Update current_company and current_company_workspace
        User::where('id', $subcontractor->id)->update([
            'current_company' => $request->current_company,
            'current_company_workspace' => $request->current_company_workspace,
        ]);

        // Get updated user
        $updatedSubcontractor = User::find($subcontractor->id);

        return $this->success([
            'current_company' => $updatedSubcontractor->current_company,
            'current_company_workspace' => $updatedSubcontractor->current_company_workspace,
            'company_name' => $customer->name,
            'company_email' => $customer->email,
        ], 'Current company updated successfully');
    }
}
