<?php

namespace App\Http\Controllers;

use App\Models\ProductOrganisation;
use Illuminate\Http\Request;
use App\Models\Payroll;
use App\Models\PayrollEmployee;
use App\Models\User;
use Exception;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
use App\Interfaces\UserRepositoryInterface;
use App\Interfaces\OrganisationRepositoryInterface;
use App\Interfaces\UserOrgPermissionRepositoryInterface;
use App\Interfaces\SuperAdminRepositoryInterface;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use App\Imports\DataImport;
use PhpParser\Builder\FunctionLike;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use App\Mail\AdminInvitation;

class SuperAdminController extends Controller
{
    private UserRepositoryInterface $userRepository;
    private OrganisationRepositoryInterface $organisationRepository;

    private UserOrgPermissionRepositoryInterface $userOrgPermissionRepository;
    private SuperAdminRepositoryInterface $superAdminRepository;

    public function __construct(SuperAdminRepositoryInterface $superAdminRepository, UserRepositoryInterface $userRepository, OrganisationRepositoryInterface $organisationRepository, UserOrgPermissionRepositoryInterface $userOrgPermissionRepository)
    {
        $this->middleware('auth:api', ['except' => ['getDemoAccount']]);
        $this->userRepository = $userRepository;
        $this->organisationRepository = $organisationRepository;
        $this->userOrgPermissionRepository = $userOrgPermissionRepository;
        $this->superAdminRepository = $superAdminRepository;
    }

    //Get All Organisations
    public function getAllOrganisations(Request $request)
    {
        try {
            $user = Auth::user();
            $searchQuery = $request->searchQuery ?? '';
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $status = $request->status;
            $limit = (int) $request->limit ?? 10;
            $organisations = $this->superAdminRepository->getAllOrg($startDate, $endDate, $status, $limit, $searchQuery );

            return response()->json([
                'status' => 'success',
                'data' => $organisations,
                'message' => 'All Organisations'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function auditTrail(Request $request)
    {
        try {
            $user = Auth::user();
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $limit = (int) $request->limit ?? 15;
            $trails = $this->superAdminRepository->getAppAudits($startDate, $endDate, $limit);

            return response()->json([
                'status' => 'success',
                'data' => $trails,
                'message' => 'Audit Trails'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function orgAuditTrail(Request $request)
    {
        try {
            $user = Auth::user();
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $limit = (int) $request->limit ?? 15;
            $orgId = $request->orgId;
            $trails = $this->superAdminRepository->getOrgAudits($startDate, $endDate, $limit, $orgId);

            return response()->json([
                'status' => 'success',
                'data' => $trails,
                'message' => 'Audit Trails'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function dashboardMetrics(Request $request)
    {
        try {
            $user = Auth::user();
            $metrics = $this->superAdminRepository->dashboardMetrics();

            return response()->json([
                'status' => 'success',
                'data' => $metrics,
                'message' => 'All Metrics'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function billingHistory(Request $request)
    {
        try {
            $user = Auth::user();
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $status = $request->status;
            $limit = (int) $request->limit ?? 15;
            $billings = $this->superAdminRepository->billingHistory($startDate, $endDate, $status, $limit);

            return response()->json([
                'status' => 'success',
                'data' => $billings,
                'message' => 'All Billing History'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function subscriptionHistory(Request $request)
    {
        try {
            $user = Auth::user();
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $status = $request->status ?? null;
            $plan = $request->plan;
            $duration = $request->duration;
            $limit = (int) $request->limit ?? 15;
            $subscribtions = $this->superAdminRepository->subscriptionsHistory($startDate, $endDate, $status, $limit, $duration, $plan);

            return response()->json([
                'status' => 'success',
                'data' => $subscribtions,
                'message' => 'All Subscribtions History'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function activateOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;

            $org = $this->superAdminRepository->getOrg($orgId);

            if (!$org) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Organisation not found!'
                ], 500);
            }
            $organisation = $this->superAdminRepository->activateOrg($orgId);

            return response()->json([
                'status' => 'success',
                'data' => $organisation,
                'message' => 'Activated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deactivateOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $org = $this->superAdminRepository->getOrg($orgId);
            
            if (!$org) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Organisation not found!'
                ], 500);
            }
            $organisation = $this->superAdminRepository->disactivateOrg($orgId);

            return response()->json([
                'status' => 'success',
                'data' => $organisation,
                'message' => 'Disactivated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    //Get All Payroll History
    public function getAllPayroll(Request $request)
    {
        try {
            $user = Auth::user();
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $status = $request->status;
            $limit = (int) $request->limit ?? 10;
            $paygroup = $request->payGroup;
            $payrolls = $this->superAdminRepository->payrollHistory($startDate, $endDate, $status, $limit, $paygroup);

            return response()->json([
                'status' => 'success',
                'data' => $payrolls,
                'message' => 'All Payrolls'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function OrganisationChart(Request $request)
    {
        try {
            $user = Auth::user();
            $year = $request->year ?? Carbon::now()->year;
            $organisationChart = $this->superAdminRepository->organisationList($year);
            $limit = (int) $request->limit ?? 15;

            return response()->json([
                'status' => 'success',
                'data' => $organisationChart,
                'message' => 'Organisation Chart'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function payrollChart(Request $request)
    {
        try {
            $user = Auth::user();
            $year = $request->year ?? Carbon::now()->year;
            $payrollChart = $this->superAdminRepository->payrollList($year);

            return response()->json([
                'status' => 'success',
                'data' => $payrollChart,
                'message' => 'Payroll Chart'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function createRole(Request $request)
    {
        try {
            $name = $request->roleName;
            $userName = $request->userName;
            $email = $request->email;
            $permissions = $request->permissions;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'roleName' => 'string',
                'permissions' => 'array',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            //Create New User 
            $password = Str::random(8);
            $userData = [
                'email' => $email,
                'password' => Hash::make($password),
                'user_type' => 'super-admin',
                'organisation_id' => 61,
                'is_registered' => true,
                'is_active' => true
            ];
            $user = $this->userRepository->createUser($userData);

            //Create Profiles Based on the success above
            list($firstName, $lastName) = explode(' ', $userName);
            $mainProfile = ["first_name" => $firstName, "last_name" => $lastName];
            $bankProfile = [];
            $jobProfile = [];

            $baseProfile = $this->userRepository->createAdmin($user->id, $mainProfile, $bankProfile, $jobProfile);

            //Create Role
            $role = $this->superAdminRepository->createRoles($name, $permissions, $user);

            //Send Mail
            $mailData = [
                "email" => $email,
                "password" => $password,
                "name" => $userName,
            ];

            Mail::to($email)->send(new AdminInvitation($mailData));

            return response()->json([
                'status' => 'success',
                'data' => $role,
                'message' => 'User added successfully'
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function readPermissions(Request $request)
    {
        try {
            $permissionLists = $this->superAdminRepository->readPermissions();

            return response()->json([
                'status' => 'success',
                'data' => $permissionLists,
                'message' => 'Permission Lists'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getRolesList(Request $request)
    {
        try {
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $limit = (int) $request->limit ?? 15;
            $roleLists = $this->superAdminRepository->getRoles($startDate, $endDate, $limit);

            return response()->json([
                'status' => 'success',
                'data' => $roleLists,
                'message' => 'Roles Lists'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
    public function getOneRoleList(Request $request)
    {
        try {
            $roleId = $request->roleId;
            $roleLists = $this->superAdminRepository->getSingleRecord($roleId);
            $limit = (int) $request->limit ?? 15;
            return response()->json([
                'status' => 'success',
                'data' => $roleLists,
                'message' => 'Roles Lists'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function updateRole(Request $request)
    {
        try {
            $roleId = $request->roleId;
            $roleName = $request->roleName;
            $permissions = $request->permissions ?? null;

            //Add Validations
            $validator = Validator::make($request->all(), [
                'roleName' => 'string',
                'permissions' => 'array',
            ]);
            // Check if validation fails
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }
            $roleList = $this->superAdminRepository->getSingleRecord($roleId);

            if (empty($roleList)) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Role does not exist'
                ], 400);
            }
            $role = $this->superAdminRepository->updateRoleRecord($roleId, $roleName, $permissions);

            return response()->json([
                'status' => 'success',
                'data' => $role,
                'message' => 'Role Deleted'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }


    public function deleteRole(Request $request)
    {
        try {
            $roleId = $request->roleId;

            $roleList = $this->superAdminRepository->getSingleRecord($roleId);

            if (empty($roleList)) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Role does not exist'
                ], 400);
            }

            $role = $this->superAdminRepository->deleteRoleRecord($roleId);

            return response()->json([
                'status' => 'success',
                'data' => $role,
                'message' => 'Roles Lists'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function payrollPieChart(Request $request)
    {
        try {
            $payroll = $this->superAdminRepository->payrollPieChart();

            return response()->json([
                'status' => 'success',
                'data' => $payroll,
                'message' => 'Payroll List'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function activateSubscription(Request $request)
    {
        try {
            $user = Auth::user();
            $subId = $request->subId;

            $subscription = $this->superAdminRepository->getSubscription($subId);

            if (!$subscription) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Subscription not found!'
                ], 500);
            }
            $sub = $this->superAdminRepository->activateSubscription($subId);

            return response()->json([
                'status' => 'success',
                'data' => $sub,
                'message' => 'Activated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deactivateSubscription(Request $request)
    {
        try {
            $user = Auth::user();
            $subId = $request->subId;

            $subscription = $this->superAdminRepository->getSubscription($subId);

            if (!$subscription) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Subscription not found!'
                ], 500);
            }
            $sub = $this->superAdminRepository->deactivateSubscription($subId);

            return response()->json([
                'status' => 'success',
                'data' => $sub,
                'message' => 'Disactivated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function activateOrgProduct(Request $request)
    {
        try {
            $user = Auth::user();
            $orgProductId = $request->orgProductId;

            $orgProduct = $this->superAdminRepository->getSingleProductOrg($orgProductId);

            if (!$orgProduct) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Product not registered on this account!'
                ], 500);
            }
            $sub = $this->superAdminRepository->activateOrganisationProduct($orgProductId);

            return response()->json([
                'status' => 'success',
                'data' => $sub,
                'message' => 'Activated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function productAccessUpdate(Request $request)
    {
        try {
            $user = Auth::user();
            $validator = Validator::make($request->all(), [
                'organization_products' => 'array',
            ]);
            if ($validator->fails()) {
                return response()->json([
                    'status' => 'failed',
                    'message' => $validator->errors()->first(),
                ], 422);
            }

            foreach ($request->organization_products as $key => $organization_product) {
                $productOrg = ProductOrganisation::where("id", $organization_product['id'])->first();
                $productOrg->is_active = $organization_product['is_active'];
                $productOrg->save();
            }

            return response()->json([
                'status' => 'success',
                'data' => [],
                'message' => 'Organization product access successfully'
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deactivateOrgProduct(Request $request)
    {
        try {
            $user = Auth::user();
            $orgProductId = $request->orgProductId;

            $orgProduct = $this->superAdminRepository->getSingleProductOrg($orgProductId);

            if (!$orgProduct) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Product not registered on this account!'
                ], 500);
            }
            $sub = $this->superAdminRepository->deactivateOrganisationProduct($orgProductId);

            return response()->json([
                'status' => 'success',
                'data' => $sub,
                'message' => 'Deactivated successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getRegistedProductList(Request $request)
    {
        try {
            $startDate = $request->startDate ?? '2020-01-01';
            $endDate = $request->endDate ?? '3000-01-01';
            $limit = (int) $request->limit ?? 15;
            $status = $request->status;
            $productName = $request->product;
            $searchText = $request->searchText;

            // Fetch all products
            $products = $this->organisationRepository->getPayratyProducts();

            // Find the payroll product ID
            $payrollProduct = null;
            foreach ($products as $product) {
                if ($product['name'] === $productName) {
                    $payrollProduct = $product;
                    break;
                }
            }

            $regsiteredProducts = $this->superAdminRepository->getRegisteredProduct($payrollProduct['id'], $startDate, $endDate, $limit);

            return response()->json([
                'status' => 'success',
                'data' => $regsiteredProducts,
                'message' => 'Registered Products Lists'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function getDemoAccount(Request $request)
    {
        try {
            $demoAccount = [
                "email" => env("DEMO_ACCOUNT")
            ];
            return response()->json([
                'status' => 'success',
                'data' => $demoAccount,
                'message' => 'Demo Account Info'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function checkProductActiveInventory(Request $request)
    {
        try {
        $productId = 2;

        $user = Auth::user();
        $userRole = $user->user_type;
        $orgId = $user->organisation_id;
        $orgProduct = $this->superAdminRepository->checkProductActive($productId,$orgId);


        if (!$orgProduct || !$orgProduct->is_active) {
            if ($userRole === 'employee') {
                return response()->json([
                    'status' => 'success',
                    'message' => 'No access',
                    'redirectUrl' => '/no-access'
                ], 433);
            } else {
                return response()->json([
                    'status' => 'success',
                    'message' => 'No access',
                    'redirectUrl' => '/all-products/no-access'
                ], 433);
            }
        } 
        return response()->json([
            'status' => 'success',
            'message' => 'Access granted',
        ], 200);
         }   catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }

    public function deleteOrg(Request $request)
    {
        try {
            $user = Auth::user();
            $orgId = $request->orgId;
            $org = $this->superAdminRepository->getOrg($orgId);

            if (!$org) {
                return response()->json([
                    'status' => 'failed',
                    'data' => [],
                    'message' => 'Organisation not found!'
                ], 500);
            }
            $organisation = $this->superAdminRepository->deleteOrg($orgId);

            return response()->json([
                'status' => 'success',
                'data' => $organisation,
                'message' => 'Organisation Deleted successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'failed',
                'message' => $e->getMessage(),
            ], 500);
        }
    }
}
