package models

import (
	"database/sql"
	"encoding/json"
	"time"
)

/* ==============================================================
   🔹 NULL TYPE WRAPPERS
   MSSQL sql.Null* tiplerini JSON'a dönüştürürken:
   - null yerine "", 0 veya false döndürür
   - frontend'de (Vue/Quasar) doğrudan okunabilir hale getirir
============================================================== */

// 🟦 STRING
type NullString struct {
	sql.NullString
}

func (ns *NullString) MarshalJSON() ([]byte, error) {
	if ns.Valid {
		return json.Marshal(ns.String)
	}
	return json.Marshal("")
}

func (ns *NullString) UnmarshalJSON(b []byte) error {
	var s *string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	if s != nil {
		ns.Valid = true
		ns.String = *s
	} else {
		ns.Valid = false
		ns.String = ""
	}
	return nil
}

// 🟩 INT32
type NullInt32 struct {
	sql.NullInt32
}

func (ni *NullInt32) MarshalJSON() ([]byte, error) {
	if ni.Valid {
		return json.Marshal(ni.Int32)
	}
	return json.Marshal(0)
}

func (ni *NullInt32) UnmarshalJSON(b []byte) error {
	var n *int32
	if err := json.Unmarshal(b, &n); err != nil {
		return err
	}
	if n != nil {
		ni.Valid = true
		ni.Int32 = *n
	} else {
		ni.Valid = false
		ni.Int32 = 0
	}
	return nil
}

// 🟧 INT16
type NullInt16 struct {
	sql.NullInt16
}

func (ni *NullInt16) MarshalJSON() ([]byte, error) {
	if ni.Valid {
		return json.Marshal(ni.Int16)
	}
	return json.Marshal(0)
}

func (ni *NullInt16) UnmarshalJSON(b []byte) error {
	var n *int16
	if err := json.Unmarshal(b, &n); err != nil {
		return err
	}
	if n != nil {
		ni.Valid = true
		ni.Int16 = *n
	} else {
		ni.Valid = false
		ni.Int16 = 0
	}
	return nil
}

// 🟨 FLOAT64
type NullFloat64 struct {
	sql.NullFloat64
}

func (nf *NullFloat64) MarshalJSON() ([]byte, error) {
	if nf.Valid {
		return json.Marshal(nf.Float64)
	}
	return json.Marshal(0.0)
}

func (nf *NullFloat64) UnmarshalJSON(b []byte) error {
	var f *float64
	if err := json.Unmarshal(b, &f); err != nil {
		return err
	}
	if f != nil {
		nf.Valid = true
		nf.Float64 = *f
	} else {
		nf.Valid = false
		nf.Float64 = 0
	}
	return nil
}

// 🟥 BOOL
type NullBool struct {
	sql.NullBool
}

func (nb *NullBool) MarshalJSON() ([]byte, error) {
	if nb.Valid {
		return json.Marshal(nb.Bool)
	}
	return json.Marshal(false)
}

func (nb *NullBool) UnmarshalJSON(b []byte) error {
	var v *bool
	if err := json.Unmarshal(b, &v); err != nil {
		return err
	}
	if v != nil {
		nb.Valid = true
		nb.Bool = *v
	} else {
		nb.Valid = false
		nb.Bool = false
	}
	return nil
}

// 🟪 TIME
type NullTime struct {
	sql.NullTime
}

func (nt *NullTime) MarshalJSON() ([]byte, error) {
	if nt.Valid {
		return json.Marshal(nt.Time.Format("2006-01-02 15:04:05"))
	}
	return json.Marshal(nil)
}

func (nt *NullTime) UnmarshalJSON(b []byte) error {
	var s *string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	if s != nil && *s != "" {
		t, err := time.Parse("2006-01-02 15:04:05", *s)
		if err != nil {
			return err
		}
		nt.Valid = true
		nt.Time = t
	} else {
		nt.Valid = false
	}
	return nil
}
