<?php
namespace boru\boruai\Openai;

use boru\boruai\Openai\Api\Endpoints\UploadsAPI;
use boru\boruai\Openai\Models\BaseModel;
use Exception;

class OpenAIUpload extends BaseModel {
    /** @var string */
    private $id;
    /** @var string */
    private $object = "upload";
    /** @var int */
    private $bytes;
    /** @var int */
    private $createdAt;
    /** @var string */
    private $filename;
    /** @var string */
    private $purpose;
    /** @var string */
    private $status;
    /** @var int */
    private $expiresAt;
    /** @var OpenAIFile */
    private $file;

    /**
     * When true, use the Uploads API (create -> addPart -> complete).
     * When false (default), use legacy Files API (POST /v1/files).
     *
     * Rationale: as of 2026-03-10, /v1/uploads was returning server_error in the field,
     * while /v1/files worked. Keep Uploads API available for future/large-file flows.
     *
     * @var bool
     */
    private $useUploadsApi = false;

    public function __construct($filenameOrArray=null) {
        if ($filenameOrArray !== null) {
            if (is_array($filenameOrArray)) {
                $this->loadFromArray($filenameOrArray);
            } else if (is_string($filenameOrArray)) {
                $this->filename = $filenameOrArray;
            }
        }
    }

    /**
     * Opt-in to Uploads API usage.
     * @param bool $use
     * @return $this
     */
    public function useUploadsApi($use=true) {
        $this->useUploadsApi = $use ? true : false;
        return $this;
    }

    public function loadFromArray($array) {
        $this->id = $array["id"];
        $this->object = $array["object"];
        $this->bytes = $array["bytes"];
        $this->createdAt = $array["created_at"];
        $this->filename = $array["filename"];
        $this->purpose = $array["purpose"];
        $this->status = $array["status"];
        $this->expiresAt = $array["expires_at"];
        if (isset($array["file"])) {
            $this->file = new OpenAIFile($array["file"]);
        }
    }

    public function toArray() {
        $array = [];
        $array["id"] = $this->id;
        $array["object"] = $this->object;
        $array["bytes"] = $this->bytes;
        $array["created_at"] = $this->createdAt;
        $array["filename"] = $this->filename;
        $array["purpose"] = $this->purpose;
        $array["status"] = $this->status;
        $array["expires_at"] = $this->expiresAt;
        if ($this->file) {
            $array["file"] = $this->file->toArray();
        }
    }

    public function id($id=null) {
        if ($id) {
            $this->id = $id;
        }
        return $this->id;
    }
    public function object($object=null) {
        if ($object) {
            $this->object = $object;
        }
        return $this->object;
    }
    public function bytes($bytes=null) {
        if ($bytes) {
            $this->bytes = $bytes;
        }
        return $this->bytes;
    }
    public function createdAt($createdAt=null) {
        if ($createdAt) {
            $this->createdAt = $createdAt;
        }
        return $this->createdAt;
    }
    public function filename($filename=null) {
        if ($filename) {
            $this->filename = $filename;
        }
        return $this->filename;
    }
    public function purpose($purpose=null) {
        if ($purpose) {
            $this->purpose = $purpose;
        }
        return $this->purpose;
    }
    public function status($status=null) {
        if ($status) {
            $this->status = $status;
        }
        return $this->status;
    }
    public function expiresAt($expiresAt=null) {
        if ($expiresAt) {
            $this->expiresAt = $expiresAt;
        }
        return $this->expiresAt;
    }
    public function file($file=null) {
        if ($file) {
            $this->file = $file;
        }
        return $this->file;
    }

    /**
     * Upload a file.
     *
     * Default path: legacy Files API via OpenAIFile::upload().
     * Opt-in path: Uploads API, when ->useUploadsApi(true) is set.
     */
    public function upload($filename=null,$mime=null) {
        if($filename === null) {
            if($this->filename === null) {
                throw new Exception("Filename is required to upload a file");
            }
            $filename = $this->filename;
        }
        if(!file_exists($filename)) {
            throw new Exception("File not found: ".$filename);
        }
        if($mime === null) {
            $mime = mime_content_type($filename);
        }

        // Default: use /v1/files (stable)
        if(!$this->useUploadsApi) {
            $file = OpenAIFile::upload($filename, $this->purpose);
            $this->file($file);
            return $this;
        }

        // Optional: use Uploads API (create -> addPart -> complete)
        $response = UploadsAPI::create([
            "purpose" => $this->purpose,
            // just the filename, not the full path
            "filename" => basename($filename),
            "bytes" => filesize($filename),
            "mime_type" => $mime
        ]);

        $this->loadFromArray($response->asArray());

        $parts = [];

        // May need to chunk the file here.. but for now we'll just do a single part upload
        $parameters = [
            "data"=>fopen($filename,"r")
        ];
        $response = UploadsAPI::addPart($this->id, $parameters);
        $parts[] = $response->get("id");

        // complete upload
        $response = UploadsAPI::complete($this->id,["part_ids"=>$parts]);
        $this->loadFromArray($response->asArray());
        return $this;
    }
}
