<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }
class YXXSMWA_Core {
    private static $i=null;
    public static function instance(){if(null===self::$i){self::$i=new self();}return self::$i;}
    private function __construct(){if(!extension_loaded('gd')){return;}$this->hooks();}
    private function hooks(){add_filter('wp_handle_upload',[$this,'auto_watermark_on_upload'],99);add_filter('media_row_actions',[$this,'add_media_row_actions'],10,2);add_action('admin_post_yxxsmwa_watermark_single',[$this,'handle_watermark_single']);add_action('admin_post_yxxsmwa_remove_watermark',[$this,'handle_remove_watermark']);add_action('add_attachment',[$this,'backup_on_add_attachment']);add_action('add_meta_boxes',[$this,'add_watermark_meta_box']);add_action('wp_ajax_yxxsmwa_watermark_attachment',[$this,'ajax_watermark_attachment']);}
    public static function get_settings(){return['text_enabled'=>get_option('yxxsmwa_text_enabled',true),'text_content'=>get_option('yxxsmwa_text_content',get_bloginfo('name')),'text_size'=>(int)get_option('yxxsmwa_text_size',12),'text_color'=>get_option('yxxsmwa_text_color','#ffffff'),'text_opacity'=>(int)get_option('yxxsmwa_text_opacity',60),'position'=>get_option('yxxsmwa_position','bottom-right'),'image_sizes'=>(array)get_option('yxxsmwa_image_sizes',['large','full']),'auto_watermark'=>get_option('yxxsmwa_auto_watermark',true),'img_enabled'=>get_option('yxxsmwa_image_watermark_enabled',false),'img_id'=>(int)get_option('yxxsmwa_image_watermark_id',0),'img_opacity'=>(int)get_option('yxxsmwa_image_watermark_opacity',50)];}
    public function auto_watermark_on_upload($f){$s=self::get_settings();if(!$s['auto_watermark']||!empty($f['error'])){return $f;}if(!preg_match('/^image\/(jpeg|png|gif|webp)$/',$f['type']??'')){return $f;}$orig=$f['file'].'.orig';@copy($f['file'],$orig);self::regenerate_on_upload($f['file'],$s);self::apply_watermark($f['file'],$s);self::watermark_all_sizes($f['file'],$s);return $f;}

    public static function regenerate_on_upload($fp,$s){if(empty($s['image_sizes'])){return;}global $wpdb;$cache_key='yxxsmwa_attached_'.md5($fp);$id=wp_cache_get($cache_key,'yxxsmwa');if(false===$id){$upload_dir=wp_upload_dir();$relative_path=str_replace($upload_dir['basedir'].'/','',$fp);$id=$wpdb->get_var($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value=%s",$relative_path)); // phpcs:ignore
        wp_cache_set($cache_key,$id,'yxxsmwa',3600);}if(!$id){return;}if(function_exists('wp_generate_attachment_metadata')){$m=wp_generate_attachment_metadata((int)$id,$fp);wp_update_attachment_metadata((int)$id,$m);}}
    public function add_media_row_actions($a,$p){if(!wp_attachment_is_image($p->ID)){return $a;}$u=wp_nonce_url(admin_url('admin-post.php?action=yxxsmwa_watermark_single&id='.$p->ID),'yxxsmwa_watermark_'.$p->ID);$a['yxxsmwa_watermark']='<a href="'.esc_url($u).'">'.esc_html__('Watermark','yxx-smart-watermark').'</a>';return $a;}
    public function handle_watermark_single(){if(!isset($_GET['id'],$_GET['_wpnonce'])){wp_die('Missing params.');}$i=(int)$_GET['id'];if(!$i||!wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])),'yxxsmwa_watermark_'.$i)){wp_die('Security fail.');}if(!current_user_can('upload_files')){wp_die('Permission.');}$f=get_attached_file($i);if(!$f||!file_exists($f)){wp_die('Not found.');}self::backup_original_file($i);self::apply_watermark($f,self::get_settings());if(function_exists('wp_generate_attachment_metadata')){$m=wp_generate_attachment_metadata($i,$f);wp_update_attachment_metadata($i,$m);}wp_safe_redirect(add_query_arg('yxxsmwa_done','1',wp_get_referer()));exit;}
    public function handle_remove_watermark(){if(!isset($_GET['id'],$_GET['_wpnonce'])){wp_die('Missing params.');}$i=(int)$_GET['id'];if(!$i||!wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])),'yxxsmwa_remove_'.$i)){wp_die('Security fail.');}if(!current_user_can('upload_files')){wp_die('Permission.');}$o=get_post_meta($i,'_yxxsmwa_original_path',true);$c=get_attached_file($i);if($o&&file_exists($o)){copy($o,$c);if(function_exists('wp_generate_attachment_metadata')){$m=wp_generate_attachment_metadata($i,$c);wp_update_attachment_metadata($i,$m);}}wp_safe_redirect(add_query_arg('yxxsmwa_removed','1',wp_get_referer()));exit;}
    public static function apply_watermark($p,$s=null){if(null===$s){$s=self::get_settings();}if(!extension_loaded('gd')){return new WP_Error('no_gd','GD missing');}if(!file_exists($p)){return new WP_Error('no_file','Not found');}$i=getimagesize($p);if(!$i){return new WP_Error('invalid','Invalid');}$m=$i['mime'];$w=$i[0];$h=$i[1];if($w<100||$h<100){return true;}if($w>6000||$h>6000){return new WP_Error('size','Too large');}$img=self::create_from($p,$m);if(!$img){return new WP_Error('gd','Create fail');}if(in_array($m,['image/png','image/gif','image/webp'],true)){imagealphablending($img,true);imagesavealpha($img,true);}if(!empty($s['img_enabled'])&&!empty($s['img_id'])){self::apply_img($img,$w,$h,$s);}if(!empty($s['text_enabled'])&&!empty($s['text_content'])){self::apply_txt($img,$w,$h,$s);}$ok=self::save_img($img,$p,$m);imagedestroy($img);return $ok?true:new WP_Error('save','Save fail');}
        private static function find_font(){static $f=null;if(null!==$f){return $f;}$plugin_font=plugin_dir_path(__FILE__).'../fonts/NotoSansSC-Regular.ttf';if(file_exists($plugin_font)){$f=$plugin_font;return $f;}$upload_dir=wp_upload_dir();$dirs=[$upload_dir['basedir'],'/usr/share/fonts','/usr/share/fonts/truetype/dejavu','/usr/share/fonts/truetype','C:\\Windows\\Fonts'];foreach($dirs as $d){foreach(['DejaVuSans.ttf','DejaVuSans-Bold.ttf','Arial.ttf','arial.ttf','FreeSans.ttf','NotoSans-Regular.ttf','Ubuntu-R.ttf','NotoSansSC-Regular.ttf']as $ff){$fp=$d.'/'.$ff;if(file_exists($fp)){$f=$fp;return $f;}}}return false;}

    private static function apply_txt($img,$iw,$ih,$s){$h=ltrim($s['text_color'],'#');$a=round(127*(1-$s['text_opacity']/100));$c=imagecolorallocatealpha($img,hexdec(substr($h,0,2)),hexdec(substr($h,2,2)),hexdec(substr($h,4,2)),(int)$a);$z=$s['text_size'];$f=self::find_font();if($f){$box=imagettfbbox($z,0,$f,$s['text_content']);$tw=abs($box[4]-$box[0]);$th=abs($box[5]-$box[1]);$p=self::pos($iw,$ih,$tw+10,$th+10,$s['position']);imagettftext($img,$z,0,$p['x'],$p['y']+$th,$c,$f,$s['text_content']);}else{$z2=max(1,min(5,$s['text_size']));$tw=imagefontwidth($z2)*strlen($s['text_content']);$th=imagefontheight($z2);$p=self::pos($iw,$ih,$tw,$th,$s['position']);imagestring($img,$z2,$p['x'],$p['y'],$s['text_content'],$c);}}
    private static function apply_img($img,$iw,$ih,$s){$wp=get_attached_file($s['img_id']);if(!$wp||!file_exists($wp)){return;}$wi=getimagesize($wp);if(!$wi){return;}$wm=self::create_from($wp,$wi['mime']);if(!$wm){return;}$ww=$wi[0];$wh=$wi[1];$mw=$iw*0.4;$mh=$ih*0.4;if($ww>$mw||$wh>$mh){$r=min($mw/$ww,$mh/$wh);$nw=(int)($ww*$r);$nh=(int)($wh*$r);$s2=imagecreatetruecolor($nw,$nh);imagealphablending($s2,false);imagesavealpha($s2,true);imagecopyresampled($s2,$wm,0,0,0,0,$nw,$nh,$ww,$wh);imagedestroy($wm);$wm=$s2;$ww=$nw;$wh=$nh;}$p=self::pos($iw,$ih,$ww,$wh,$s['position']);imagecopymerge($img,$wm,$p['x'],$p['y'],0,0,$ww,$wh,(int)$s['img_opacity']);imagedestroy($wm);}
    private static function pos($iw,$ih,$ew,$eh,$p){$m=20;switch($p){case'top-left':return['x'=>$m,'y'=>$m];case'top-center':return['x'=>(int)(($iw-$ew)/2),'y'=>$m];case'top-right':return['x'=>$iw-$ew-$m,'y'=>$m];case'center-left':return['x'=>$m,'y'=>(int)(($ih-$eh)/2)];case'center':return['x'=>(int)(($iw-$ew)/2),'y'=>(int)(($ih-$eh)/2)];case'center-right':return['x'=>$iw-$ew-$m,'y'=>(int)(($ih-$eh)/2)];case'bottom-left':return['x'=>$m,'y'=>$ih-$eh-$m];case'bottom-center':return['x'=>(int)(($iw-$ew)/2),'y'=>$ih-$eh-$m];default:return['x'=>$iw-$ew-$m,'y'=>$ih-$eh-$m];}}
    private static function create_from($p,$m){switch($m){case'image/jpeg':return@imagecreatefromjpeg($p);case'image/png':return@imagecreatefrompng($p);case'image/gif':return@imagecreatefromgif($p);case'image/webp':return@imagecreatefromwebp($p);default:return false;}}
    private static function save_img($img,$p,$m){switch($m){case'image/jpeg':return@imagejpeg($img,$p,90);case'image/png':return@imagepng($img,$p,8);case'image/gif':return@imagegif($img,$p);case'image/webp':return@imagewebp($img,$p,90);default:return false;}}
    public static function backup_original_file($id){$o=get_post_meta($id,'_yxxsmwa_original_path',true);if($o&&file_exists($o)){return $o;}$f=get_attached_file($id);if(!$f||!file_exists($f)){return false;}$d=wp_upload_dir();$bd=$d['basedir'].'/yxxsmwa-backups';if(!is_dir($bd)){wp_mkdir_p($bd);}$bp=$bd.'/'.basename($f).'.orig';if(copy($f,$bp)){update_post_meta($id,'_yxxsmwa_original_path',$bp);return $bp;}return false;}
    public function backup_on_add_attachment($id){$s=self::get_settings();if(!$s['auto_watermark']){return;}$f=get_attached_file($id);if(!$f||!file_exists($f)){return;}$o=$f.'.orig';if(file_exists($o)){update_post_meta($id,'_yxxsmwa_original_path',$o);}}
    public function add_watermark_meta_box(){add_meta_box('yxxsmwa_watermark_actions',__('Watermark','yxx-smart-watermark'),[$this,'render_watermark_meta_box'],'attachment','side');}
    public function render_watermark_meta_box($p){if(!wp_attachment_is_image($p->ID)){echo '<p>'.esc_html__('Not an image.','yxx-smart-watermark').'</p>';return;}$wu=wp_nonce_url(admin_url('admin-post.php?action=yxxsmwa_watermark_single&id='.$p->ID),'yxxsmwa_watermark_'.$p->ID);$ru=wp_nonce_url(admin_url('admin-post.php?action=yxxsmwa_remove_watermark&id='.$p->ID),'yxxsmwa_remove_'.$p->ID);?><p><a href="<?php echo esc_url($wu);?>" class="button button-primary" style="width:100%;text-align:center;display:block;"><?php esc_html_e('Apply Watermark','yxx-smart-watermark');?></a></p><p><a href="<?php echo esc_url($ru);?>" class="button" style="width:100%;text-align:center;display:block;" onclick="return confirm('<?php esc_attr_e('Remove watermark from this image?','yxx-smart-watermark');?>');"><?php esc_html_e('Remove Watermark','yxx-smart-watermark');?></a></p><?php }
    public function ajax_watermark_attachment(){if(!isset($_POST['_ajax_nonce'],$_POST['attachment_id'])){wp_send_json_error(['message'=>'Missing params.']);}check_ajax_referer('yxxsmwa_watermark_attachment','_ajax_nonce');if(!current_user_can('upload_files')){wp_send_json_error(['message'=>'Permission.']);}$id=(int)sanitize_text_field(wp_unslash($_POST['attachment_id']));if(!$id||!wp_attachment_is_image($id)){wp_send_json_error(['message'=>'Invalid.']);}$r=self::watermark_attachment_sizes($id);$e=array_filter($r,function($x){return is_wp_error($x);});empty($e)?wp_send_json_success(['message'=>'Watermarked.']):wp_send_json_error(['message'=>'Some failed.']);}
    public static function watermark_attachment_sizes($id){$r=[];$sizes=self::get_settings()['image_sizes'];$meta=wp_get_attachment_metadata($id);$base=dirname(get_attached_file($id));self::backup_original_file($id);foreach($sizes as$sn){$fp='';if($sn==='full'){$fp=get_attached_file($id);}elseif(isset($meta['sizes'][$sn]['file'])){$fp=$base.'/'.$meta['sizes'][$sn]['file'];}if($fp&&file_exists($fp)){$r[$sn]=self::apply_watermark($fp);}}return $r;}
    public static function watermark_all_sizes($fp,$s){$id=0;global$wpdb;$cache_key='yxxsmwa_attached_'.md5($fp);$id=wp_cache_get($cache_key,'yxxsmwa');if(false===$id){$upload_dir=wp_upload_dir();$relative_path=str_replace($upload_dir['basedir'].'/','',$fp);$id=$wpdb->get_var($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value=%s",$relative_path)); // phpcs:ignore
        wp_cache_set($cache_key,$id,'yxxsmwa',3600);}if(!$id){return;}self::watermark_attachment_sizes((int)$id);}
}
