<?php

namespace App\Http\Controllers\API;

use App\Exports\DownloadHelper;
use App\Exports\RequirementExport;
use App\Http\Controllers\Controller;
use App\Http\Requests\API\Requirement\ClosedRequest;
use App\Http\Requests\API\Requirement\CreateOrUpdateRequest;
use App\Http\Requests\API\Requirement\LinkPlanRequest;
use App\Http\Requests\API\Requirement\BatchCreateRequest;
use App\Http\Resources\API\AssetRequirementResource;
use App\Http\Resources\API\RequirementResource;
use App\Imports\RequirementImport;
use App\Models\Approval;
use App\Models\Asset;
use App\Models\Enums\ActionObjectType;
use App\Models\Enums\FileObjectType;
use App\Models\Enums\RequirementStatus;
use App\Models\Enums\ObjectAction;
use App\Models\Plan;
use App\Models\Requirement;
use App\Repositories\ActionRepository;
use App\Services\File\FileAssociationService;
use App\Services\History\ModelChangeDetector;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

class RequirementController extends Controller
{
    use DownloadHelper;

    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $requirements = Requirement::filter($request->all())
            ->where('company_id',Auth::user()->company_id)
            ->orderBy('created_at', $request->input('sort','desc'))
            ->with(['createdBy', 'plan','group','asset.parent'])
            ->paginate($request->get('page_size') ?? 10);

        return AssetRequirementResource::collection($requirements);
    }

//    public function byAsset(Request $request,string $assetId)
//    {
//        $requirements=Requirement::filter($request->all())->with(['createdBy', 'plan','group']) ->where('asset_id', $assetId)->simplePaginate();
//
//        return AssetRequirementResource::collection($requirements);
//    }

    public function export(Request $request)
    {
        return $this->downloadExcelHelper(
            new RequirementExport(),
            "requirement",
            $request->get("extension"),
        );
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(FileAssociationService $service, CreateOrUpdateRequest $request)
    {
        $requirement = new Requirement();

        $requirement->mergeFillable([
            'company_id', 'created_by',
        ]);

        $service->check(
            $request->get("file_ids", []),
            FileObjectType::REQUIREMENT,
            $request->get("file_uuid"),
        );

        $requirement->fill([
            ...$request->all(),
            'company_id' => Auth::user()->company_id,
            'description' => $request->description? (new \App\Services\File\ImageUrlService)->interceptImageUrl($request->description) : null,
            'created_by' => Auth::id(),
        ]);
        $requirement->save();

        ActionRepository::createRequirement(
            $requirement, ObjectAction::CREATED
        );

        $service->association($requirement->id);

        return $this->created();
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        $requirement = Requirement::query()->findOrFail($id);

        return new RequirementResource($requirement);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(CreateOrUpdateRequest $request, string $id)
    {
        $requirement = Requirement::findOrFail($id);

        $requirement->fill([
            ...$request->all(),
            'description' => $request->description? (new \App\Services\File\ImageUrlService)->interceptImageUrl($request->description) : null,
        ]);
        $changes = ModelChangeDetector::detector(ActionObjectType::REQUIREMENT, $requirement);
        $requirement->save();

        ActionRepository::createRequirement(
            $requirement, ObjectAction::EDITED,objectChanges: $changes
        );
        return $this->noContent();
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $requirement = Requirement::findOrFail($id);

        $requirement->delete();

        Approval::query()->where('object_type','requirement')->where('object_id',$id)->delete();
        ActionRepository::createRequirement(
            $requirement, ObjectAction::DELETED
        );

        return $this->noContent();
    }

    public function close(Request $request,string $id){
        $requirement = Requirement::findOrFail($id);

        $requirement->status = RequirementStatus::CLOSED->value;
        $changes = ModelChangeDetector::detector(ActionObjectType::REQUIREMENT, $requirement);
        $requirement->save();

        ActionRepository::createRequirement(
            $requirement,
            ObjectAction::CLOSED,
            $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null,
            objectChanges: $changes
        );

        return $this->noContent();
    }

    public function start(Request $request, string $id)
    {
        $requirement = Requirement::findOrFail($id);

        $requirement->status = RequirementStatus::ACTIVE->value;
        $changes = ModelChangeDetector::detector(ActionObjectType::REQUIREMENT, $requirement);
        $requirement->save();

        ActionRepository::createRequirement(
            $requirement,
            ObjectAction::STARTED,
            $request->comment?(new \App\Services\File\ImageUrlService)->interceptImageUrl($request->comment) : null,
            objectChanges: $changes
        );

        return $this->noContent();
    }

    public function linkPlan(LinkPlanRequest $request, string $planId)
    {
        $plan = Plan::query()->findOrFail($planId);

        Requirement::query()->where("asset_id", $plan->asset_id)
            ->whereIn('id', $request->get("requirement_ids"))
            ->update([
                'plan_id' => $plan->id,
            ]);

        return $this->noContent();
    }

    public function unlinkPlan(LinkPlanRequest $request)
    {
        Requirement::query()->whereIn('id', $request->get("requirement_ids"))
            ->update([
                'plan_id' => null,
            ]);

        return $this->noContent();
    }

    public function batchStore(BatchCreateRequest $request)
    {
        $requirementsData = $request->all();
        $companyId = Auth::user()->company_id;
        $created_by = Auth::id();
        DB::transaction(function () use ($requirementsData,$companyId,$created_by) {
            foreach ($requirementsData as $k => $data) {
                $requirement = new Requirement();
                $requirement->mergeFillable([
                    'company_id', 'created_by',
                ]);
                if($k != 0){
                    $requirementsData[$k]["requirement_group_id"] = $requirementsData[$k]["requirement_group_id"] == 'ditto'?$requirementsData[$k-1]["requirement_group_id"]:$requirementsData[$k]["requirement_group_id"];
                    $requirementsData[$k]["priority"] =  $requirementsData[$k]["priority"] == 'ditto'?  $requirementsData[$k-1]["priority"]: $requirementsData[$k]["priority"];
                }
                $requirement->fill([
                    ...$requirementsData[$k],
                    'company_id' => $companyId,
                    'created_by' =>  $created_by,
                    'status' => RequirementStatus::ACTIVE,
                    'mailto' => [],
                ]);
                $requirement->save();

                 ActionRepository::createRequirement(
                     $requirement, ObjectAction::CREATED
                 );
            }
        });
        return $this->created();
    }

    public function import(Request $request)
    {
        Excel::import(new RequirementImport(), $request->file("file"));

        return $this->created();
    }
}