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

class Backup extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        if (!$this->session->userdata('admin_logged_in')) {
            redirect('Auth');
        }
    }

    /**
     * Generates a full DB backup (.sql) and forces it to download
     * in the browser. Tries mysqldump first (fast, exact); if that
     * is unavailable (common on shared hosting with exec() disabled),
     * falls back to a pure-PHP dump using CodeIgniter's DB layer.
     */
    public function download_backup()
    {
        set_time_limit(300); // large DB sathi timeout vadhवला

        $db_host = $this->db->hostname;
        $db_user = $this->db->username;
        $db_pass = $this->db->password;
        $db_name = $this->db->database;

        $filename = 'backup_' . $db_name . '_' . date('Y-m-d_H-i-s') . '.sql';
        $filepath = sys_get_temp_dir() . '/' . $filename;

        $mysqldump_ok = $this->_try_mysqldump($db_host, $db_user, $db_pass, $db_name, $filepath);

        if (!$mysqldump_ok || !file_exists($filepath) || filesize($filepath) === 0) {
            $this->_php_based_backup($db_name, $filepath);
        }

        if (!file_exists($filepath) || filesize($filepath) === 0) {
            show_error('Backup file tayar houu shakle nahi. Server settings check kara.');
            return;
        }

        // Force download
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($filepath));

        readfile($filepath);
        unlink($filepath); // temp file clean up
        exit;
    }

    /**
     * Attempts a mysqldump-based backup. Returns TRUE on success.
     * If exec() is disabled on the server, this will simply fail
     * silently and the caller falls back to the PHP-based method.
     */
    private function _try_mysqldump($host, $user, $pass, $dbname, $filepath)
    {
        if (!function_exists('exec')) {
            return FALSE;
        }

        // Live server var jar mysqldump PATH madhe nasel, tar
        // full path dyaव, e.g. '/usr/bin/mysqldump'
        $mysqldump_path = 'mysqldump';

        $command = sprintf(
            '%s --host=%s --user=%s --password=%s %s > %s 2>&1',
            escapeshellcmd($mysqldump_path),
            escapeshellarg($host),
            escapeshellarg($user),
            escapeshellarg($pass),
            escapeshellarg($dbname),
            escapeshellarg($filepath)
        );

        @exec($command, $output, $return_var);

        return ($return_var === 0);
    }

    /**
     * Pure-PHP fallback backup using CI's own DB connection.
     * Works even when exec()/mysqldump is not available.
     */
    private function _php_based_backup($db_name, $filepath)
    {
        $tables = $this->db->list_tables();

        $sql  = "-- Backup for database: $db_name\n";
        $sql .= "-- Generated: " . date('Y-m-d H:i:s') . "\n\n";
        $sql .= "SET FOREIGN_KEY_CHECKS=0;\n\n";

        foreach ($tables as $table) {
            $create = $this->db->query("SHOW CREATE TABLE `$table`")->row_array();
            $sql .= "DROP TABLE IF EXISTS `$table`;\n";
            $sql .= $create['Create Table'] . ";\n\n";

            $rows = $this->db->query("SELECT * FROM `$table`")->result_array();
            foreach ($rows as $row) {
                $values = array_map(function ($v) {
                    if ($v === null) return 'NULL';
                    return "'" . $this->db->escape_str($v) . "'";
                }, array_values($row));

                $sql .= "INSERT INTO `$table` VALUES (" . implode(',', $values) . ");\n";
            }
            $sql .= "\n";
        }

        $sql .= "SET FOREIGN_KEY_CHECKS=1;\n";

        file_put_contents($filepath, $sql);
    }
}
