<?php

namespace App\Http\Livewire\Pages\Patch;

use GuzzleHttp\Exception\RequestException;
use App\Models\ConfSmartupdate;
use App\Models\MasterPhpVer;
use App\Models\TabPatchFile;
use Livewire\Component;
use GuzzleHttp\Client;
use ZipArchive;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;

class PatchCreate extends Component
{
    public $projects = [];
    public $branches = [];
    public $selectedProject;
    public $selectedBranch;
    public $startCommit = '';
    public $endCommit = '';
    public $fileChanges = [], $filePathChanges = [];
    public $searchProject = 'SPN64Bits';
    public $UNINSTALL = '$b=1';
    public $PATCHNAME, $PDATE, $PHP_VERSION, $PLEVEL, $PCODE, $MAJOR_VERSION, $PDESC, $Remark, $POWNER, $PAPPROVEDATE, $PTYPE, $SPECIFIC_CUSTOMER, $PATCHCODE, $PATCHCODE_SERVER;

    public function mount()
    {
        $this->PDATE = date("Y-m-d H:i:s");
        $this->PAPPROVEDATE = date("Y-m-d H:i:s");
        $this->PLEVEL = 'High';
        $this->PATCHCODE = 'function updatePatchFile($PATH_APP,$content){
            $handle = fopen($PATH_APP, "w");
            fputs($handle,base64_decode($content));
            fclose($handle);
        }
        updatePatchFile("$$file_name_0","$$file_data_0");
        $PATCH_STATUS="OK";';

        $nextPid = ConfSmartupdate::max('PID') + 1;
        $this->PATCHCODE_SERVER = '$a=1;
        Query2Array("select * from tab_patch_file where ptid=' . "'" . $nextPid . "'" . '");
            for($i=0;$i<count($fid);$i++){
                ${\'file_name_\'.$i}=$file_name[$i];
                ${\'file_data_\'.$i}=$file_data[$i];
            }
        $max=count($fid);';
    }
    public function updatedSearchProject()
    {
        $this->fetchProjects();
    }
    public function fetchProjects()
    {
        $client = new Client([
            'headers' => [
                'Authorization' => 'Bearer ' . env('GITLAB_API_TOKEN'),
                'Accept' => 'application/json',
            ],
            'verify' => false,
        ]);

        $page = 1;
        $perPage = 100;
        $response = $client->get(env('GITLAB_API_URL') . '/projects', [
            'query' => [
                'membership' => true,
                'min_access_level' => 30,
                'search' => $this->searchProject,
                'per_page' => $perPage,
            ],
        ]);
        $this->projects = json_decode($response->getBody(), true);
        $this->dispatchBrowserEvent('projects-fetched');
    }
    public function updatedSelectedProject($value)
    {
        $this->fetchBranches($value);
    }
    public function fetchBranches($projectId)
    {
        $client = new Client([
            'headers' => [
                'Authorization' => 'Bearer ' . env('GITLAB_API_TOKEN'),
                'Accept' => 'application/json',
            ],
            'verify' => false,
        ]);

        $response = $client->get(env('GITLAB_API_URL') . "/projects/{$projectId}/repository/branches");
        $this->branches = json_decode($response->getBody(), true);
    }
    public function getChangedFiles()
    {
        $client = new Client([
            'headers' => [
                'Authorization' => 'Bearer ' . env('GITLAB_API_TOKEN'),
                'Accept' => 'application/json',
            ],
            'verify' => false,
        ]);

        try {
            $response = $client->get(env('GITLAB_API_URL') . "/projects/{$this->selectedProject}/repository/compare", [
                'query' => [
                    'from' => $this->startCommit,
                    'to' => $this->endCommit,
                ],
            ]);

            $data = json_decode($response->getBody(), true);
            foreach ($data['diffs'] as $file) {
                $this->filePathChanges[] = $file['new_path'];
            }

            $this->fileChanges = $this->buildTree($data['diffs']);
        } catch (\Throwable $th) {
            $data = '';
        }
        $this->dispatchBrowserEvent('files-fetched', ['fileChanges' => $this->fileChanges]);
    }

    private function buildTree($files)
    {
        $tree = [];
        foreach ($files as $file) {
            $path = explode('/', $file['new_path']);
            $current = &$tree;
            foreach ($path as $part) {
                if (!isset($current[$part])) {
                    $current[$part] = [];
                }
                $current = &$current[$part];
            }
            // $current['id'] = $file['fid'];
        }
        return $tree;
    }
    // $changedFiles = [];

    // foreach ($data['diffs'] as $file) {
    //     $changedFiles[] = $file['new_path'];
    // }

    // $zip = new ZipArchive;
    // $zipFileName = storage_path('app/changed_files.zip');

    // if ($zip->open($zipFileName, ZipArchive::CREATE) === TRUE) {
    //     foreach ($changedFiles as $file) {
    //         $fileResponse = $client->get(env('GITLAB_API_URL')."/projects/{$this->selectedProject}/repository/files/" . urlencode($file) . '/raw', [
    //             'query' => [
    //                 'ref' => $this->endCommit,
    //             ],
    //         ]);
    //         $fileContent = $fileResponse->getBody();
    //         $zip->addFromString($file, $fileContent);
    //     }
    //     $zip->close();
    // }

    //     return response()->download($zipFileName);
    // }

    public function save()
    {
        // $this->validate([
        //     'PATCHNAME' => 'required|string|max:255',
        //     'PDATE' => 'required|date',
        //     'PHP_VERSION' => 'required|integer',
        //     'PLEVEL' => 'required|string|max:255',
        //     'PCODE' => 'required|string|max:255',
        //     'MAJOR_VERSION' => 'required|string|max:255',
        //     'PDESC' => 'required|string|max:255',
        //     'Remark' => 'required|string|max:255',
        //     'POWNER' => 'required|string|max:255',
        //     'PAPPROVEDATE' => 'required|date',
        //     'PTYPE' => 'required|string|max:255',
        //     'PATCHCODE' => 'required|string',
        //     'UNINSTALL' => 'required|string|max:255',
        //     'PATCHCODE_SERVER' => 'required|string',
        // ]);

        $codePhpVersion = MasterPhpVer::find($this->PHP_VERSION);

        $confSmartUpdate = new ConfSmartUpdate();
        $confSmartUpdate->PATCHNAME = $this->PATCHNAME;
        $confSmartUpdate->PDATE = $this->PDATE;
        $confSmartUpdate->PHP_VERSION_ID = $this->PHP_VERSION;
        $confSmartUpdate->PLEVEL = $this->PLEVEL;
        $confSmartUpdate->PCODE = $this->PCODE;
        $confSmartUpdate->MAJOR_VERSION = $this->MAJOR_VERSION;
        $confSmartUpdate->PDESC = $this->PDESC;
        $confSmartUpdate->Remark = $this->Remark;
        $confSmartUpdate->POWNER = $this->POWNER;
        $confSmartUpdate->PAPPROVEDATE = $this->PAPPROVEDATE;
        $confSmartUpdate->PTYPE = $this->PTYPE;
        $confSmartUpdate->PATCHCODE = ($codePhpVersion->check_code ?? '') . "  " . $this->PATCHCODE;
        $confSmartUpdate->UNINSTALL = $this->UNINSTALL;
        $confSmartUpdate->PATCHCODE_SERVER = $this->PATCHCODE_SERVER;
        $confSmartUpdate->save();

        if (count($this->filePathChanges) > 0) {
            foreach ($this->filePathChanges as $file) {

                $filedata = $this->getFileContentFromGit($file, $this->endCommit);

                $filePath = $this->formatFilePath($file);

                $filepath = new TabPatchFile;
                $filepath->ptid = $confSmartUpdate->PID;
                $filepath->file_name = $filePath;
                $filepath->file_data = base64_encode($filedata);
                $filepath->save();
            }
        }


        // session()->flash('message', 'Patch details saved successfully.');
        return redirect()->route('patch.index')->with('message', 'Patch details saved successfully.');
    }
    private function formatFilePath($file)
    {
        if (strpos($file, 'SPN/') !== false) {
            return str_replace("SPN/", "../SPN/", $file);
        } else if (strpos($file, 'spn/') !== false) {
            return str_replace("spn/", "../spn/", $file);
        } else {
            return str_replace("IE5DEV.shippingnet", ".", $file);
        }
    }

    private function getFileContentFromGit($filePath, $commit)
    {
        $token = env('GITLAB_API_TOKEN');

        $client = new Client([
            'base_uri' => 'https://idemo.netbay.co.th/gitlab/api/v4/',
            'headers' => [
                'Authorization' => "Bearer $token",
                'Accept' => 'application/json',
            ],
            'verify' => false,
        ]);

        try {
            $response = $client->get("projects/$this->selectedProject/repository/files/" . urlencode($filePath) . "/raw", [
                'query' => ['ref' => $commit]
            ]);
            $statusCode = $response->getStatusCode();
            $content = $response->getBody()->getContents();

            if ($statusCode == 200) {
                return $content;
            } else {
                throw new \Exception("Failed to fetch file. Status code: $statusCode");
            }
        } catch (RequestException $e) {
            return '';
            // throw $e;
        } catch (\Exception $e) {
            return '';
            // throw $e;
        }
    }

    public function loadPage($page)
    {
        $this->emit('menuChanged', $page);
    }
    public function render()
    {
        return view('livewire.pages.patch.patch-create');
    }
}
