<?php

declare(strict_types=1);

namespace App\Http\Controllers\Market;

use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\Market\CooperativeMember;
use App\Models\Market\Organization;
use App\Models\User;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hypervel\Support\Facades\Hash;
use Hypervel\Support\Facades\Response;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use App\Enums\UserActions;
use App\Enums\UserTypes;
use Hypervel\Support\Str;

class CooperativeController
{
    public function listCooperatives(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ViewOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $query = Organization::where('is_active', true)->where('type', 'COOPERATIVE');
        
        $cooperatives = $query->withCount('members')->get();

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

    public function getCooperative(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ViewOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $hashkey = $request->input('hashkey');
        if (!$hashkey) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $cooperative = Organization::where('hashkey', $hashkey)->with(['members.user.userInfo'])->first();
        
        if (!$cooperative) {
            return ResponseHelper::returnError('Cooperative not found', 404);
        }

        $currentUserMembership = null;
        $user = Auth::user();
        if ($user) {
            $currentUserMembership = CooperativeMember::where('organization_id', $cooperative->id)
                ->where('user_id', $user->id)
                ->first();
        }

        return response()->json([
            'success' => true,
            'data' => $cooperative,
            'is_member' => $currentUserMembership !== null,
            'membership' => $currentUserMembership,
        ]);
    }

    public function createCooperative(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::CreateOrganization)) {
            return ResponseHelper::returnUnauthorized();
        }

        $name = $request->input('name');
        $address = $request->input('address', '');
        $registrationNumber = $request->input('registration_number', '');
        $cin = $request->input('cin', '');
        $tin = $request->input('tin', '');
        $cooperativeType = $request->input('cooperative_type', '');
        $cooperativeCategory = $request->input('cooperative_category', '');
        $registrationDate = $request->input('registration_date', null);
        $contactPerson = $request->input('contact_person', '');
        $contactNumber = $request->input('contact_number', '');
        $contactEmail = $request->input('contact_email', '');

        if (empty(trim($name ?? ''))) {
            return ResponseHelper::returnError('Cooperative name is required');
        }

        $cooperative = new Organization([
            'hashkey' => Str::random(64),
            'name' => trim($name),
            'type' => 'COOPERATIVE',
            'address' => trim($address ?? ''),
            'registration_number' => trim($registrationNumber),
            'cin' => trim($cin),
            'tin' => trim($tin),
            'cooperative_type' => trim($cooperativeType),
            'cooperative_category' => trim($cooperativeCategory),
            'registration_date' => $registrationDate,
            'contact_person' => trim($contactPerson),
            'contact_number' => trim($contactNumber),
            'contact_email' => trim($contactEmail),
            'is_active' => true,
            'created_by' => Auth::id(),
        ]);

        if ($cooperative->save()) {
            return ResponseHelper::returnSuccessResponse($cooperative, $cooperative->hashkey, 'Cooperative created successfully');
        }

        return ResponseHelper::returnError('Failed to create cooperative');
    }

    public function joinCooperative(Request $request)
    {
        $user = Auth::user();
        if (!$user) {
            return ResponseHelper::returnUnauthorized();
        }

        $cooperativeHash = $request->input('cooperative_hash');
        if (!$cooperativeHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $cooperative = Organization::where('hashkey', $cooperativeHash)->first();
        if (!$cooperative) {
            return ResponseHelper::returnError('Cooperative not found', 404);
        }

        // Check if already a member
        $existing = CooperativeMember::where('organization_id', $cooperative->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existing) {
            return ResponseHelper::returnError('Already a member of this cooperative');
        }

        $memberFields = $request->only([
            'role', 'membership_type', 'membership_level', 'officer_position', 'officer_level',
            'concurrent_position', 'concurrent_level', 'cooperative_name_alt', 'cooperative_position', 'year_beginning',
            'priority_sector', 'common_bond', 'vulnerability_classifications',
            'philsys_id', 'sss_number', 'pagibig_number',
            'slp_track', 'slp_association_name', 'listahanan_id', 'fourtps_household_id',
            'tupad_category', 'tupad_insurance_beneficiary_name', 'tupad_insurance_beneficiary_relation',
            'preferred_occupation', 'nsrp_skills', 'employment_status', 'program_participation',
        ]);

        $member = new CooperativeMember(array_merge($memberFields, [
            'organization_id' => $cooperative->id,
            'user_id' => $user->id,
            'role' => $request->input('role', 'MEMBER'),
            'joined_at' => now(),
            'is_active' => true,
        ]));

        if ($member->save()) {
            // Sync with user settings
            $settings = $user->settings ?? [];
            $cooperatives = $settings['cooperatives'] ?? [];
            if (!in_array($cooperativeHash, $cooperatives)) {
                $cooperatives[] = $cooperativeHash;
                $settings['cooperatives'] = $cooperatives;
                $user->settings = $settings;
                $user->save();
            }
            return ResponseHelper::returnSuccessResponse($member, $member->hashkey, 'Successfully joined cooperative');
        }

        return ResponseHelper::returnError('Failed to join cooperative');
    }

    public function addMember(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $cooperativeHash = $request->input('cooperative_hash');
        $userHash = $request->input('user_hash');

        if (!$cooperativeHash || !$userHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $cooperative = Organization::where('hashkey', $cooperativeHash)->first();
        $targetUser = User::where('hashkey', $userHash)->first();

        if (!$cooperative || !$targetUser) {
            return ResponseHelper::returnError('Cooperative or User not found', 404);
        }

        $existing = CooperativeMember::where('organization_id', $cooperative->id)
            ->where('user_id', $targetUser->id)
            ->first();

        if ($existing) {
            return ResponseHelper::returnError('User is already a member');
        }

        $memberFields = $request->only([
            'role', 'membership_type', 'membership_level', 'officer_position', 'officer_level',
            'concurrent_position', 'concurrent_level', 'cooperative_name_alt', 'cooperative_position', 'year_beginning',
            'priority_sector', 'common_bond', 'vulnerability_classifications',
            'philsys_id', 'sss_number', 'pagibig_number',
            'slp_track', 'slp_association_name', 'listahanan_id', 'fourtps_household_id',
            'tupad_category', 'tupad_insurance_beneficiary_name', 'tupad_insurance_beneficiary_relation',
            'preferred_occupation', 'nsrp_skills', 'employment_status', 'program_participation',
        ]);

        $member = new CooperativeMember(array_merge($memberFields, [
            'organization_id' => $cooperative->id,
            'user_id' => $targetUser->id,
            'role' => $request->input('role', 'MEMBER'),
            'joined_at' => now(),
            'is_active' => true,
        ]));

        if ($member->save()) {
            return ResponseHelper::returnSuccessResponse($member, $member->hashkey, 'Member added to cooperative');
        }

        return ResponseHelper::returnError('Failed to add member');
    }

    public function updateMember(Request $request)
    {
        if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::ManageOrganizations)) {
            return ResponseHelper::returnUnauthorized();
        }

        $memberHash = $request->input('member_hash');
        if (!$memberHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $member = CooperativeMember::where('hashkey', $memberHash)->first();
        if (!$member) {
            return ResponseHelper::returnError('Member record not found', 404);
        }

        $memberFields = $request->only([
            'role', 'membership_type', 'membership_level', 'officer_position', 'officer_level',
            'concurrent_position', 'concurrent_level', 'cooperative_name_alt', 'cooperative_position', 'year_beginning',
            'is_active'
        ]);

        $member->fill($memberFields);

        if ($member->save()) {
            return ResponseHelper::returnSuccessResponse($member, $member->hashkey, 'Membership details updated');
        }

        return ResponseHelper::returnError('Failed to update membership details');
    }

    public function registerMember(Request $request)
    {
        $user = Auth::user();
        if (!$user) {
            return ResponseHelper::returnUnauthorized();
        }

        if (!UserPermissions::isActionPermitted($user->acct_type, UserActions::JoinCooperative)) {
            return ResponseHelper::returnUnauthorized();
        }

        $cooperativeHash = $request->input('cooperative_hash');
        if (!$cooperativeHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $cooperative = Organization::where('hashkey', $cooperativeHash)->first();
        if (!$cooperative) {
            return ResponseHelper::returnError('Cooperative not found', 404);
        }

        // Check if already a member
        $existing = CooperativeMember::where('organization_id', $cooperative->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existing) {
            return ResponseHelper::returnError('Already a member of this cooperative');
        }

        $memberFields = $request->only([
            'role', 'membership_type', 'membership_level', 'officer_position', 'officer_level',
            'concurrent_position', 'concurrent_level', 'cooperative_name_alt', 'cooperative_position', 'year_beginning',
            'priority_sector', 'common_bond', 'vulnerability_classifications',
            'philsys_id', 'sss_number', 'pagibig_number',
            'slp_track', 'slp_association_name', 'listahanan_id', 'fourtps_household_id',
            'tupad_category', 'tupad_insurance_beneficiary_name', 'tupad_insurance_beneficiary_relation',
            'preferred_occupation', 'nsrp_skills', 'employment_status', 'program_participation',
        ]);

        $member = new CooperativeMember(array_merge($memberFields, [
            'hashkey' => Str::random(64),
            'organization_id' => $cooperative->id,
            'user_id' => $user->id,
            'role' => $request->input('role', 'MEMBER'),
            'joined_at' => now(),
            'is_active' => true,
            'created_by' => $user->id,
        ]));

        if ($member->save()) {
            // Sync with user settings
            $settings = $user->settings ?? [];
            $cooperatives = $settings['cooperatives'] ?? [];
            if (!is_array($cooperatives)) $cooperatives = [];
            
            if (!in_array($cooperativeHash, $cooperatives)) {
                $cooperatives[] = $cooperativeHash;
                $settings['cooperatives'] = $cooperatives;
                $user->settings = $settings;
                $user->save();
            }
            // Upgrade a plain USER to COOP_MEMBER on cooperative registration.
            // Never downgrade a higher type (COORDINATOR, OPERATOR, etc.).
            if ($user->acct_type === UserTypes::USER) {
                $user->acct_type = UserTypes::COOP_MEMBER;
                $user->save();
            }
            return ResponseHelper::returnSuccessResponse($member, $member->hashkey, 'Successfully registered as a cooperative member');
        }

        return ResponseHelper::returnError('Failed to register');
    }

    public function publicCompleteMembership(Request $request)
    {
        $userHashkey = $request->input('user_hashkey');
        $coopHash    = $request->input('cooperative_hash');

        if (!$userHashkey || !$coopHash) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $user = User::where('hashkey', $userHashkey)->first();
        if (!$user) {
            return response()->json(['success' => false, 'message' => 'User not found'], 404);
        }

        $cooperative = Organization::where('hashkey', $coopHash)
            ->where('type', 'COOPERATIVE')
            ->where('is_active', true)
            ->first();

        if (!$cooperative) {
            return response()->json(['success' => false, 'message' => 'Cooperative not found'], 404);
        }

        $existing = CooperativeMember::where('organization_id', $cooperative->id)
            ->where('user_id', $user->id)
            ->first();

        if ($existing) {
            return response()->json(['success' => false, 'message' => 'Already a member'], 409);
        }

        $member = new CooperativeMember(array_merge(
            $request->only([
                'membership_type', 'membership_level', 'year_beginning',
                'officer_position', 'officer_level', 'concurrent_position', 'concurrent_level',
                'cooperative_position', 'cooperative_name_alt',
                'priority_sector', 'common_bond', 'vulnerability_classifications',
                'philsys_id', 'sss_number', 'pagibig_number',
                'slp_track', 'slp_association_name', 'listahanan_id', 'fourtps_household_id',
                'tupad_category', 'tupad_insurance_beneficiary_name', 'tupad_insurance_beneficiary_relation',
                'preferred_occupation', 'nsrp_skills', 'employment_status', 'program_participation',
            ]),
            [
                'hashkey'         => Str::random(64),
                'organization_id' => $cooperative->id,
                'user_id'         => $user->id,
                'role'            => 'MEMBER',
                'joined_at'       => now(),
                'is_active'       => true,
                'created_by'      => $user->id,
            ]
        ));
        $member->save();

        $settings                 = $user->settings ?? [];
        $settings['cooperatives'] = array_unique(array_merge($settings['cooperatives'] ?? [], [$coopHash]));
        $user->settings           = $settings;
        $user->save();

        return response()->json(['success' => true, 'message' => 'Membership application submitted successfully.']);
    }

    public function publicGetCooperative(Request $request, string $hkey)
    {
        try {
            $cooperative = Organization::where('hashkey', $hkey)
                ->where('type', 'COOPERATIVE')
                ->where('is_active', true)
                ->select(['id', 'hashkey', 'name', 'type', 'cooperative_type', 'cooperative_category', 'contact_person', 'contact_number', 'address'])
                ->first();
        } catch (\Throwable $e) {
            return Response::json(['success' => false, 'message' => 'Service temporarily unavailable'], 500);
        }

        if (!$cooperative) {
            return Response::json(['success' => false, 'message' => 'Cooperative not found'], 404);
        }

        return Response::json(['success' => true, 'data' => $cooperative]);
    }

    public function publicRegisterMember(Request $request)
    {
        $hkey = $request->input('cooperative_hash');
        if (!$hkey) {
            return ResponseHelper::returnIncorrectDetails();
        }

        $cooperative = Organization::where('hashkey', $hkey)
            ->where('type', 'COOPERATIVE')
            ->where('is_active', true)
            ->first();

        if (!$cooperative) {
            return Response::json(['success' => false, 'message' => 'Cooperative not found'], 404);
        }

        try {
            $validated = $request->validate([
                'name'          => 'required|string|max:255',
                'username'      => 'required|string|max:255|unique:users,username',
                'mobile_number' => ['required', 'string', 'max:20', 'unique:users,mobile_number', 'regex:/^(09|\+639)\d{9}$/'],
                'password'      => 'required|string|min:6',
            ]);
        } catch (\Hypervel\Validation\ValidationException $e) {
            return Response::json(['success' => false, 'errors' => $e->errors()], 422);
        }

        $parentUser = User::where('id', $cooperative->created_by)->first()
            ?? User::where('acct_type', 'COORDINATOR')->first()
            ?? User::orderBy('id')->first();

        if (!$parentUser) {
            return Response::json(['success' => false, 'message' => 'No valid parent user found'], 500);
        }

        $user = new User();
        $user->username      = $validated['username'];
        $user->name          = $validated['name'];
        $user->mobile_number = $validated['mobile_number'];
        $user->password      = Hash::make($validated['password']);
        $user->parentuid     = $parentUser->id;
        $user->acct_type     = 'user';
        $user->active        = true;
        $user->save();

        return Response::json([
            'success'      => true,
            'user_hashkey' => $user->hashkey,
            'message'      => 'Account created. Please complete your membership application.',
        ], 201);
    }


}
