<?php

namespace App\Jobs;

use App\ReportJob;
use App\SeverancePayment;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Bus\Batchable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class GenerateExcelSingleReportOne implements ShouldQueue
{
	use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
	
	protected $reportJob;
	protected $severancePayment;
	
	/**
	 * The number of seconds the job can run before timing out.
	 *
	 * @var int
	 */
	public $timeout = 3600;
	
	/**
	 * Indicate if the job should be marked as failed on timeout.
	 *
	 * @var bool
	 */
	public $failOnTimeout = false;
	
	/**
	 * Create a new job instance.
	 *
	 * @param ReportJob $reportJob
	 * @param SeverancePayment $severancePayment
	 */
	public function __construct(ReportJob $reportJob, SeverancePayment $severancePayment)
	{
		$this->onQueue(config('queue.connections.redis.queue'));
		$this->reportJob = $reportJob;
		$this->severancePayment = $severancePayment;
	}
	
	/**
	 * @return bool
	 */
	public function isFailOnTimeout(): bool
	{
		return $this->failOnTimeout;
	}
	
	/**
	 * Execute the job.
	 *
	 * @return void
	 */
	public function handle()
	{
		try {
			ini_set('max_execution_time', 300);
			ini_set('memory_limit', '512M');
			
			$this->reportJob->update([
				'status'     => 'processing',
				'updated_at' => Carbon::now(),
			]);
			
			$templatePath = public_path('template/1.xlsx');
			// Suppress XML warnings from PhpSpreadsheet when loading template
			$previousErrorReporting = error_reporting(E_ERROR | E_PARSE);
			$spreadsheet = IOFactory::load($templatePath);
			error_reporting($previousErrorReporting);
			$sheet = $spreadsheet->getActiveSheet();
			
			$row = 6;
			$sheet->setCellValue('A' . $row, $this->severancePayment->employee->department->code);
			$sheet->setCellValue('B' . $row, $this->severancePayment->employee->department->name);
			$sheet->setCellValue('C' . $row, $this->severancePayment->employee->employee_code);
			$sheet->setCellValue('D' . $row, $this->severancePayment->employee->full_name);
			$sheet->setCellValue('E' . $row, $this->severancePayment->employee->date_of_birth ? Carbon::parse($this->severancePayment->employee->date_of_birth)->format('Y/m/d') : '');
			$sheet->setCellValue('F' . $row, $this->severancePayment->employee->join_date ? Carbon::parse($this->severancePayment->employee->join_date)->format('Y/m/d') : '');
			$sheet->setCellValue('G' . $row, $this->severancePayment->employee->resigned_date ? Carbon::parse($this->severancePayment->employee->resigned_date)->format('Y/m/d') : '');
			$sheet->setCellValue('H' . $row, $this->severancePayment->tenure_year);
			$sheet->setCellValue('I' . $row, $this->severancePayment->tenure_points);
			$sheet->setCellValue('J' . $row, $this->severancePayment->tenure_amount);
			$sheet->setCellValue('K' . $row, $this->severancePayment->level_points);
			$sheet->setCellValue('L' . $row, $this->severancePayment->level_amount);
			$sheet->setCellValue('M' . $row, $this->severancePayment->position_points);
			$sheet->setCellValue('N' . $row, $this->severancePayment->position_amount);
			$sheet->setCellValue('O' . $row, number_format($this->severancePayment->total_points, 2, '.', ','));
			$sheet->setCellValue('P' . $row, $this->severancePayment->total_amount);
			$sheet->setCellValue('Q' . $row, $this->severancePayment->payment_percent . "%");
			$sheet->setCellValue('R' . $row, $this->severancePayment->final_amount);
			$sheet->getStyle('A' . $row . ':R' . $row)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
			
			$row++;
			$sheet->setCellValue('A' . $row, "合計");
			$sheet->setCellValue('B' . $row, "");
			$sheet->setCellValue('C' . $row, "");
			$sheet->setCellValue('D' . $row, "");
			$sheet->setCellValue('E' . $row, "");
			$sheet->setCellValue('F' . $row, "");
			$sheet->setCellValue('G' . $row, "");
			$sheet->setCellValue('H' . $row, "");
			$sheet->setCellValue('I' . $row, $this->severancePayment->tenure_points);
			$sheet->setCellValue('J' . $row, $this->severancePayment->tenure_amount);
			$sheet->setCellValue('K' . $row, $this->severancePayment->level_points);
			$sheet->setCellValue('L' . $row, $this->severancePayment->level_amount);
			$sheet->setCellValue('M' . $row, $this->severancePayment->position_points);
			$sheet->setCellValue('N' . $row, $this->severancePayment->position_amount);
			$sheet->setCellValue('O' . $row, number_format($this->severancePayment->total_points, 2, '.', ','));
			$sheet->setCellValue('P' . $row, $this->severancePayment->total_amount);
			$sheet->setCellValue('Q' . $row, $this->severancePayment->payment_percent . "%");
			$sheet->setCellValue('R' . $row, $this->severancePayment->final_amount);
			
			$sheet->getStyle('A6:R' . $row)->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
			$sheet->setSelectedCell('A1');
			
			$savePath = public_path('report/' . $this->reportJob->code . '.xlsx');
			$writer = new Xlsx($spreadsheet);
			$writer->save($savePath);
			
			// Set Status
			$this->reportJob->update([
				'file'        => $savePath,
				'total_sheet' => 1,
				'status'      => 'success',
				'updated_at'  => Carbon::now(),
			]);
		} catch (\Exception $exception) {
			$this->reportJob->update([
				'status'     => 'failed',
				'updated_at' => Carbon::now(),
			]);
			Log::error("[GenerateExcelSingleReportOne] Generate excel single report one error [ID: {$this->severancePayment->id}]: " . $exception->getMessage());
		}
	}
}
