<?php

namespace App\Actions\Tenancy\Visit;

use App\Models\City;
use App\Models\Clinic;
use App\Models\Tenancy\Employee;
use App\Models\Tenancy\EmployeeSalary;
use App\Models\Tenancy\FinancialRevenue;
use App\Models\Tenancy\Procedure;
use App\Models\Tenancy\ProceduresPaymentLog;
use App\Models\Tenancy\Sms;
use App\Models\Tenancy\Visit;
use App\Models\Tenancy\VisitPayment;
use App\Notifications\VisitCreated;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Validation\ValidationException;

class CreateVisitsAction
{
    public function __construct(private SendCreateVisitSmsAction $sendCreateVisitSmsAction)
    {
    }
    public function execute(array $data, int $paid, bool $sms = false, bool $email = false, string $smsUrl = null): Collection
    {
        $currentTenant = tenant('unique_name');
        $clinic = Clinic::where('client_unique_name', $currentTenant)->first();
        $city = City::byCityId($clinic->city)->first();
        $visitIds = [];
        foreach ($data as $visitData) {
            $procedure = Procedure::findOrFail($visitData['procedure_id']);
            $specialist = Employee::findOrFail($visitData['specialist_id']);
            $startDate = Carbon::createFromFormat('Y-m-d H:i', $visitData['date']);
            $endDate = $startDate->copy()->addMinutes($procedure->duration);
            $overlappingVisits = Visit::overlaps($startDate, $endDate)
                ->where('specialist_id', $specialist->id);
            if ($visitIds) {
                $overlappingVisits->whereNotIn('id', $visitIds);
            }
            $overlappingVisits = $overlappingVisits->count();
            if ($overlappingVisits > 0) {
                throw ValidationException::withMessages([
                    'date' => 'Visit already exists for this date',
                ]);
            }
            $doctor = $specialist->doctor;
            $user = auth()->user();
            $visit = Visit::create([
                'specialist_id' => $specialist->id,
                'specialist_name' => $doctor->name.' '.$doctor->lastname,
                'date' => $startDate->toDateTimeString(),
                'visit_ends' => $endDate->toDateTimeString(),
                'type' => 'planned',
                'online' => true,
                'client_id' => $user->detail->id,
                'x-ray' => $visitData['x_ray'] ?? false,
            ]);

            $visit->planned_id = $visit->id;
            $visit->save();

            $clientProcedureData = [
                'specialist_id' => $specialist->id,
                'date' => now()->toDateTimeString(),
                'done_date' => now()->toDateTimeString(),
                'procedure_id' => $procedure->id,
                'price' => $procedure->price,
                'procedure_price' => $procedure->price,
                'client_id' => $user->detail->id,
                'status' => 'done',
                'visit_start_id' => $visit->id,
                'visit_current_status_id' => $visit->id,
                'planned_id' => $visit->id,
                'paid' => $paid,
            ];
            if ($paid) {
                $paidDate = Carbon::now()->toDateTimeString();
                $clientProcedureData['paid_date'] = $paidDate;
                $employeeSalary = EmployeeSalary::where('employer_id', $specialist->id)
                    ->orderBy('date', 'DESC')
                    ->first();
                if ($employeeSalary && isset($employeeSalary->salary_json[$procedure->id])) {
                    $employeePercent = 100 * (float) $employeeSalary->salary_json[$procedure->id]['fixed'] / $paid;
                    $fixed = (($paid * $employeePercent) / 100);
                    $employeeAmount = ($fixed + (($paid * $employeeSalary->salary_json[$procedure->id]['percentage']) / 100));
                    $clientProcedureData['doctor_amount'] = $employeeAmount;
                    $clientProcedureData['doctor_salary_fixed_percent'] = $employeePercent;
                } else {
                    $clientProcedureData['doctor_amount'] = 0;
                    $clientProcedureData['doctor_salary_fixed_percent'] = 0;
                }
                $visitPayment = VisitPayment::create([
                    'visit_id' => $visit->id,
                    'planned_id' => $visit->planned_id,
                    'date' => $paidDate,
                    'client_id' => $user->detail->id,
                    'specialist_id' => $specialist->id,
                    'amount' => $clientProcedureData['doctor_amount'],
                    'paid' => $paid,
                    'total_amount' => $procedure->price,
                    'cash' => 0,
                    'pos' => $paid,
                    'bank' => 999,
                ]);

                FinancialRevenue::create([
                    'date' => $paidDate,
                    'amount' => $paid - $clientProcedureData['doctor_amount'],
                    'paid' => $paid,
                    'status' => 'revenue',
                    'physical_person_name' => $user->detail->name.' '.$user->detail->lastname,
                    'physical_person_identifier' => $user->detail->personal_id,
                    'pos' => $paid,
                    'cash' => 0,
                    'employee_id' => $specialist->id,
                    'bank_id' => 999,
                    'visit_payment_id' => $visitPayment->id,
                    'comment' => 'ონლაინ ჯავშნის ანგარიშსწორება',
                    'type' => 'revenue',
                ]);
            }
            $visitProcedure = $visit->clientProcedure()->create($clientProcedureData);
            if ($paid) {
                ProceduresPaymentLog::create([
                    'paid' => $paid,
                    'doctor_amount' => $visitProcedure->doctor_amount,
                    'debt' => 0,
                    'diagnosis_id' => $visitProcedure->id,
                    'date' => $visitProcedure->paid_date,
                    'visit_payment_id' => $visitPayment->id,
                ]);
            }

            if ($sms) {
                $this->sendCreateVisitSmsAction->execute(
                    $clinic,
                    $city,
                    $doctor,
                    $startDate,
                    $user->detail->is_alien,
                    $user->detail->phone,
                    $smsUrl
                );
            }

            if ($email) {
                $user->notify(new VisitCreated());
            }
            $visitIds[] = $visit->id;
        }

        return Visit::with('clientProcedure', 'clientProcedure.procedure')
            ->whereIn('id', $visitIds)
            ->get();
    }
}
