<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Spk_produksi extends CI_Controller
{
    private $perPage = 10;

    public function __construct()
    {
        parent::__construct();
        cek_session_login();
        $this->load->model('Spk_produksi_model', 'spkProduksi');
    }

    public function index()
    {
        $data['title'] = 'SPK Produksi | '.info()['title'];
        $data['dari'] = date('01/m/Y');
        $data['sampai'] = date('d/m/Y');
        $this->template->load('main/themes', 'spk_produksi/index', $data);
    }

    public function data()
    {
        if (!$this->input->is_ajax_request()) show_404();
        $offset = max(0, (int)$this->input->post('page'));
        $allowedLimits = [10, 20, 50, 100];
        $limit = (int)$this->input->post('limit');
        if (!in_array($limit, $allowedLimits, true)) $limit = $this->perPage;
        $filters = [
            'keyword' => trim((string)$this->input->post('keyword', true)),
            'sort' => strtoupper((string)$this->input->post('sort')) === 'ASC' ? 'ASC' : 'DESC',
            'dari' => $this->toSqlDate($this->input->post('dari')),
            'sampai' => $this->toSqlDate($this->input->post('sampai')),
        ];
        $total = $this->spkProduksi->countRows($filters, 'created');
        $config = ['target'=>'#spkData','base_url'=>base_url('spk-produksi/data'),'total_rows'=>$total,'per_page'=>$limit,'link_func'=>'loadSpkProduksi'];
        $this->ajax_pagination->initialize($config);
        $rows = $this->spkProduksi->getRows($filters, $limit, $offset, 'created');
        $ids = array_column($rows, 'id_invoice');
        $data = ['rows'=>$rows, 'details'=>$this->spkProduksi->getDetails($ids), 'total'=>$total, 'offset'=>$offset];
        $this->load->view('spk_produksi/_list', $data, false);
    }

    public function cari_order()
    {
        if (!$this->input->is_ajax_request()) show_404();
        $keyword = trim((string)$this->input->post('keyword', true));
        $filters = ['keyword'=>$keyword, 'sort'=>'DESC'];
        $rows = $keyword === '' ? [] : $this->spkProduksi->getRows($filters, 8, 0, 'available');
        $this->load->view('spk_produksi/_order_results', ['rows'=>$rows], false);
    }

    public function form()
    {
        if (!$this->input->is_ajax_request()) show_404();
        $token = trim((string)$this->input->post('id', true));
        $invoiceId = (int)decrypt_url($token);
        if ($invoiceId < 1) {
            $this->output->set_status_header(400)->set_output('Order tidak valid.');
            return;
        }
        $row = $this->model_app->view_where('invoice', ['id_invoice'=>$invoiceId])->row();
        if (!$row) {
            $this->output->set_status_header(404)->set_output('Order tidak ditemukan.');
            return;
        }
        $customer = $this->model_app->view_where('konsumen', ['id'=>$row->id_konsumen])->row();
        $detail = $this->model_app->produk_cart(['invoice_detail.id_invoice'=>$invoiceId]);
        $this->load->view('spk_produksi/_form', compact('row', 'customer', 'detail', 'token'), false);
    }

    public function item_form()
    {
        if (!$this->input->is_ajax_request()) show_404();
        $detailId = (int)$this->input->post('detail_id');
        $item = $this->spkProduksi->getItem($detailId);
        if (!$item) {
            $this->output->set_status_header(404)->set_output('Item produksi tidak ditemukan.');
            return;
        }
        $customer = $this->model_app->view_where('konsumen',['id'=>$item->id_konsumen])->row();
        $draft = $this->spkProduksi->getDraft($detailId);
        $stockMaterials = $this->spkProduksi->getStockMaterials();
        $this->load->view('spk_produksi/_item_editor', compact('item','customer','draft','stockMaterials'), false);
    }

    public function save_item()
    {
        if (!$this->input->is_ajax_request()) show_404();
        $detailId = (int)$this->input->post('detail_id');
        $item = $this->spkProduksi->getItem($detailId);
        if (!$item) {
            $this->output->set_status_header(404)->set_content_type('application/json')->set_output(json_encode(['status'=>404,'msg'=>'Item tidak ditemukan.']));
            return;
        }
        $oldDraft = $this->spkProduksi->getDraft($detailId);
        $stockId = (int)$this->input->post('stock_bahan_id');
        $stockMaterial = $this->spkProduksi->getStockMaterial($stockId);
        $stockQuantity = (float)str_replace(',', '.', trim((string)$this->input->post('jumlah_bahan_plano', true)));
        if (!$stockMaterial || $stockQuantity <= 0) {
            $this->output->set_status_header(422)->set_content_type('application/json')->set_output(json_encode(['status'=>422,'msg'=>'Pilih bahan dari data stok dan isi jumlah bahan plano lebih dari 0.']));
            return;
        }
        $fields = ['plat','keterangan','jumlah_bahan_plano','ukuran_plano','ukuran_kertas_masuk','jumlah_kertas_masuk','mesin_cetak','jumlah_plat','warna_cetakan','cara_potong','cara_potong_svg','potong_mode','potong_margin','potong_gap','mulai_cetak','selesai_cetak','hasil_akhir'];
        $data = [];
        foreach ($fields as $field) {
            if ($field === 'cara_potong_svg') {
                $svg = trim((string)$this->input->post($field, false));
                $svg = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $svg);
                $svg = preg_replace('/\son[a-z]+\s*=\s*(["\']).*?\1/is', '', $svg);
                $svg = str_replace(['rgba(79,70,229,.12)', 'rgba(244,63,94,.12)'], ['#eef2ff', '#fff1f2'], $svg);
                $data[$field] = stripos($svg, '<svg') === 0 ? substr($svg, 0, 50000) : '';
            } else {
                $data[$field] = trim((string)$this->input->post($field, true));
            }
        }
        $data['plat'] = in_array($data['plat'], ['baru','lama','tanpa'], true) ? $data['plat'] : 'baru';
        $data['stock_bahan_id'] = $stockId;
        $data['jenis_nama_bahan'] = $stockMaterial->title;
        $finishing = $this->input->post('finishing');
        $allowed = ['laminating_glossy','laminating_doff','spot_uv','foil','potong_paska_cetak','pond','lem','packing'];
        $data['finishing'] = array_values(array_intersect($allowed, is_array($finishing) ? $finishing : []));
        $processMap = [
            'laminating'=>['laminating_glossy','laminating_doff'],
            'spot_uv'=>['spot_uv'],
            'foil'=>['foil'],
            'potong_paska_cetak'=>['potong_paska_cetak'],
            'pond'=>['pond'],
            'lem'=>['lem'],
            'packing'=>['packing'],
        ];
        $postedProcesses = $this->input->post('finishing_proses');
        $postedProcesses = is_array($postedProcesses) ? $postedProcesses : [];
        $data['finishing_proses'] = [];
        foreach ($processMap as $processKey=>$sourceFinishing) {
            if (!array_intersect($sourceFinishing, $data['finishing'])) continue;
            $processValues = isset($postedProcesses[$processKey]) && is_array($postedProcesses[$processKey]) ? $postedProcesses[$processKey] : [];
            $data['finishing_proses'][$processKey] = [
                'mulai'=>trim((string)(isset($processValues['mulai']) ? $processValues['mulai'] : '')),
                'selesai'=>trim((string)(isset($processValues['selesai']) ? $processValues['selesai'] : '')),
                'hasil'=>trim((string)(isset($processValues['hasil']) ? $processValues['hasil'] : '')),
            ];
        }
		$postedAdditionalPages = $this->input->post('additional_pages');
		$postedAdditionalPages = is_array($postedAdditionalPages) ? $postedAdditionalPages : [];
		$data['additional_pages'] = [];
		$stockUsages = [['stock_id'=>$stockId, 'quantity'=>$stockQuantity]];
		$oldAdditionalPages = isset($oldDraft['additional_pages']) && is_array($oldDraft['additional_pages']) ? array_values($oldDraft['additional_pages']) : [];
		$newAdditionalImages = [];
		$replacedAdditionalImages = [];
		$pagePosition = 0;
		foreach ($postedAdditionalPages as $pageKey=>$postedPage) {
			$pageIndex = $pagePosition++;
			if (!is_array($postedPage)) continue;
			$pageStockId = isset($postedPage['stock_bahan_id']) ? (int)$postedPage['stock_bahan_id'] : 0;
			$pageQuantity = isset($postedPage['jumlah_bahan_plano']) ? (float)str_replace(',', '.', trim((string)$postedPage['jumlah_bahan_plano'])) : 0;
			$pageStock = $this->spkProduksi->getStockMaterial($pageStockId);
			if (!$pageStock || $pageQuantity <= 0) {
				$this->output->set_status_header(422)->set_content_type('application/json')->set_output(json_encode(['status'=>422,'msg'=>'Pilih bahan dan isi jumlah bahan plano pada halaman tambahan '.($pageIndex + 2).'.']));
				return;
			}
			$pageSvg = isset($postedPage['cara_potong_svg']) ? trim((string)$postedPage['cara_potong_svg']) : '';
			$pageSvg = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $pageSvg);
			$pageSvg = preg_replace('/\son[a-z]+\s*=\s*(["\']).*?\1/is', '', $pageSvg);
			$pageSvg = str_replace(['rgba(79,70,229,.12)', 'rgba(244,63,94,.12)'], ['#eef2ff', '#fff1f2'], $pageSvg);
			$pageData = [
				'plat'=>in_array(isset($postedPage['plat']) ? $postedPage['plat'] : '', ['baru','lama','tanpa'], true) ? $postedPage['plat'] : 'baru',
				'keterangan'=>trim((string)(isset($postedPage['keterangan']) ? $postedPage['keterangan'] : '')),
				'stock_bahan_id'=>$pageStockId,
				'jenis_nama_bahan'=>$pageStock->title,
				'jumlah_bahan_plano'=>trim((string)$postedPage['jumlah_bahan_plano']),
				'ukuran_plano'=>trim((string)(isset($postedPage['ukuran_plano']) ? $postedPage['ukuran_plano'] : '')),
				'ukuran_kertas_masuk'=>trim((string)(isset($postedPage['ukuran_kertas_masuk']) ? $postedPage['ukuran_kertas_masuk'] : '')),
				'jumlah_kertas_masuk'=>trim((string)(isset($postedPage['jumlah_kertas_masuk']) ? $postedPage['jumlah_kertas_masuk'] : '')),
				'potong_mode'=>in_array(isset($postedPage['potong_mode']) ? $postedPage['potong_mode'] : '', ['auto','portrait','landscape'], true) ? $postedPage['potong_mode'] : 'auto',
				'potong_margin'=>'0', 'potong_gap'=>'0',
				'cara_potong'=>trim((string)(isset($postedPage['cara_potong']) ? $postedPage['cara_potong'] : '')),
				'cara_potong_svg'=>stripos($pageSvg, '<svg') === 0 ? substr($pageSvg, 0, 50000) : '',
				'mesin_cetak'=>trim((string)(isset($postedPage['mesin_cetak']) ? $postedPage['mesin_cetak'] : '')),
				'jumlah_plat'=>trim((string)(isset($postedPage['jumlah_plat']) ? $postedPage['jumlah_plat'] : '')),
				'warna_cetakan'=>trim((string)(isset($postedPage['warna_cetakan']) ? $postedPage['warna_cetakan'] : '')),
				'mulai_cetak'=>trim((string)(isset($postedPage['mulai_cetak']) ? $postedPage['mulai_cetak'] : '')),
				'selesai_cetak'=>trim((string)(isset($postedPage['selesai_cetak']) ? $postedPage['selesai_cetak'] : '')),
				'hasil_akhir'=>trim((string)(isset($postedPage['hasil_akhir']) ? $postedPage['hasil_akhir'] : '')),
			];
			$pageFinishing = isset($postedPage['finishing']) && is_array($postedPage['finishing']) ? $postedPage['finishing'] : [];
			$pageData['finishing'] = array_values(array_intersect($pageFinishing, $allowed));
			$pageData['finishing_proses'] = [];
			$pageProcesses = isset($postedPage['finishing_proses']) && is_array($postedPage['finishing_proses']) ? $postedPage['finishing_proses'] : [];
			foreach ($processMap as $processKey=>$sourceFinishing) {
				if (!array_intersect($sourceFinishing, $pageData['finishing'])) continue;
				$processValues = isset($pageProcesses[$processKey]) && is_array($pageProcesses[$processKey]) ? $pageProcesses[$processKey] : [];
				$pageData['finishing_proses'][$processKey] = ['mulai'=>trim((string)(isset($processValues['mulai'])?$processValues['mulai']:'')),'selesai'=>trim((string)(isset($processValues['selesai'])?$processValues['selesai']:'')),'hasil'=>trim((string)(isset($processValues['hasil'])?$processValues['hasil']:''))];
			}
			$oldPageImage = isset($oldAdditionalPages[$pageIndex]['gambar_spk']) ? trim((string)$oldAdditionalPages[$pageIndex]['gambar_spk']) : '';
			$fileField = 'additional_image_'.preg_replace('/[^0-9]/', '', (string)$pageKey);
			if (isset($_FILES[$fileField]) && (int)$_FILES[$fileField]['error'] !== UPLOAD_ERR_NO_FILE) {
				$pageUpload = $this->storeSpkImage($detailId, $fileField);
				if (!$pageUpload['ok']) {
					foreach ($newAdditionalImages as $uploadedImage) $this->deleteSpkImage($uploadedImage);
					$this->output->set_status_header(422)->set_content_type('application/json')->set_output(json_encode(['status'=>422,'msg'=>'Gambar halaman '.($pageIndex + 2).': '.$pageUpload['msg']]));
					return;
				}
				$pageData['gambar_spk'] = $pageUpload['path'];
				$newAdditionalImages[] = $pageUpload['path'];
				if ($oldPageImage !== '') $replacedAdditionalImages[] = $oldPageImage;
			} elseif (!empty($postedPage['gambar_hapus'])) {
				$pageData['gambar_spk'] = '';
				if ($oldPageImage !== '') $replacedAdditionalImages[] = $oldPageImage;
			} else {
				$pageData['gambar_spk'] = $oldPageImage;
			}
			$data['additional_pages'][] = $pageData;
			$stockUsages[] = ['stock_id'=>$pageStockId, 'quantity'=>$pageQuantity];
		}
		for ($removedPageIndex=count($postedAdditionalPages); $removedPageIndex<count($oldAdditionalPages); $removedPageIndex++) {
			if (!empty($oldAdditionalPages[$removedPageIndex]['gambar_spk'])) $replacedAdditionalImages[] = $oldAdditionalPages[$removedPageIndex]['gambar_spk'];
		}
        $oldImage = isset($oldDraft['gambar_spk']) ? trim((string)$oldDraft['gambar_spk']) : '';
        $newImage = '';
        if (isset($_FILES['gambar_spk']) && (int)$_FILES['gambar_spk']['error'] !== UPLOAD_ERR_NO_FILE) {
            $upload = $this->storeSpkImage($detailId);
            if (!$upload['ok']) {
                foreach ($newAdditionalImages as $uploadedImage) $this->deleteSpkImage($uploadedImage);
                $this->output->set_status_header(422)->set_content_type('application/json')->set_output(json_encode(['status'=>422,'msg'=>$upload['msg']]));
                return;
            }
            $newImage = $upload['path'];
            $data['gambar_spk'] = $newImage;
        } elseif ((string)$this->input->post('gambar_hapus', true) === '1') {
            $data['gambar_spk'] = '';
        } else {
            $data['gambar_spk'] = $oldImage;
        }
        $this->db->trans_begin();
        $savedDraft = $this->spkProduksi->saveDraft($detailId,$data,(int)$this->session->idu);
        $savedStock = $savedDraft && $this->spkProduksi->syncStockPages($detailId, $item->id_invoice, $stockUsages, (int)$this->session->idu);
        $ok = $savedDraft && $savedStock && $this->db->trans_status();
        if ($ok) {
            $this->db->trans_commit();
            if ($oldImage !== '' && $oldImage !== $data['gambar_spk']) $this->deleteSpkImage($oldImage);
            foreach (array_unique($replacedAdditionalImages) as $replacedImage) $this->deleteSpkImage($replacedImage);
        } else {
            $this->db->trans_rollback();
            if ($newImage !== '') $this->deleteSpkImage($newImage);
            foreach ($newAdditionalImages as $uploadedImage) $this->deleteSpkImage($uploadedImage);
        }
        $this->output->set_content_type('application/json')->set_output(json_encode(['status'=>$ok?200:400,'msg'=>$ok?'Draft SPK berhasil disimpan.':'Draft SPK gagal disimpan.']));
    }

    private function storeSpkImage($detailId, $fieldName = 'gambar_spk')
    {
        if (!function_exists('imagewebp')) return ['ok'=>false,'msg'=>'Server belum mendukung konversi gambar WebP.'];
        $dir = FCPATH.'uploads'.DIRECTORY_SEPARATOR.'spk_produksi'.DIRECTORY_SEPARATOR;
        if (!is_dir($dir) && !mkdir($dir, 0755, true)) return ['ok'=>false,'msg'=>'Folder penyimpanan gambar SPK tidak dapat dibuat.'];
        $config = [
            'upload_path'=>$dir,
            'allowed_types'=>'jpg|jpeg|png|webp',
            'max_size'=>5120,
            'file_ext_tolower'=>true,
            'remove_spaces'=>true,
            'encrypt_name'=>true,
        ];
        $this->load->library('upload', $config);
        $this->upload->initialize($config, true);
        if (!$this->upload->do_upload($fieldName)) {
            return ['ok'=>false,'msg'=>strip_tags($this->upload->display_errors('', ''))];
        }
        $uploaded = $this->upload->data();
        $sourcePath = $uploaded['full_path'];
        $info = @getimagesize($sourcePath);
        if (!$info || empty($info[0]) || empty($info[1])) {
            @unlink($sourcePath);
            return ['ok'=>false,'msg'=>'File yang dipilih bukan gambar yang valid.'];
        }
        switch ((int)$info[2]) {
            case IMAGETYPE_JPEG: $source = @imagecreatefromjpeg($sourcePath); break;
            case IMAGETYPE_PNG: $source = @imagecreatefrompng($sourcePath); break;
            case IMAGETYPE_WEBP: $source = @imagecreatefromwebp($sourcePath); break;
            default: $source = false;
        }
        if (!$source) {
            @unlink($sourcePath);
            return ['ok'=>false,'msg'=>'Gambar tidak dapat diproses. Gunakan JPG, PNG, atau WebP.'];
        }
        $sourceWidth = (int)$info[0];
        $sourceHeight = (int)$info[1];
        $scale = min(1, 1600 / max($sourceWidth, $sourceHeight));
        $targetWidth = max(1, (int)round($sourceWidth * $scale));
        $targetHeight = max(1, (int)round($sourceHeight * $scale));
        $canvas = imagecreatetruecolor($targetWidth, $targetHeight);
        imagealphablending($canvas, false);
        imagesavealpha($canvas, true);
        $transparent = imagecolorallocatealpha($canvas, 255, 255, 255, 127);
        imagefilledrectangle($canvas, 0, 0, $targetWidth, $targetHeight, $transparent);
        imagecopyresampled($canvas, $source, 0, 0, 0, 0, $targetWidth, $targetHeight, $sourceWidth, $sourceHeight);
        $fileName = 'spk_'.$detailId.'_'.date('YmdHis').'_'.bin2hex(random_bytes(4)).'.webp';
        $targetPath = $dir.$fileName;
        $saved = imagewebp($canvas, $targetPath, 76);
        imagedestroy($canvas);
        imagedestroy($source);
        if (realpath($sourcePath) !== realpath($targetPath)) @unlink($sourcePath);
        if (!$saved) {
            @unlink($targetPath);
            return ['ok'=>false,'msg'=>'Konversi gambar ke WebP gagal.'];
        }
        return ['ok'=>true,'path'=>'uploads/spk_produksi/'.$fileName];
    }

    private function deleteSpkImage($relativePath)
    {
        $relativePath = str_replace('\\', '/', trim((string)$relativePath));
        if (!preg_match('#^uploads/spk_produksi/[A-Za-z0-9._-]+\.webp$#i', $relativePath)) return;
        $path = FCPATH.str_replace('/', DIRECTORY_SEPARATOR, $relativePath);
        if (is_file($path)) @unlink($path);
    }

    private function toSqlDate($value)
    {
        $value = trim((string)$value);
        if ($value === '') return '';
        $date = DateTime::createFromFormat('d/m/Y', $value);
        return $date ? $date->format('Y-m-d') : '';
    }
}
