import csv
import tempfile
import unittest
from pathlib import Path

import numpy as np

from 전처리.match_targets import (
    geodesic_distance,
    heater_values,
    interpolate_between_heaters,
    provisional_heater_projection,
    read_defect_csv,
)


class MatchingTests(unittest.TestCase):
    def test_heater_channels_are_selected_by_name_and_keep_missing_values(self):
        names = np.asarray([f"상부온도{i:02d} [°C]" for i in range(1, 18)] +
                           [f"하부온도{i:02d} [°C]" for i in range(1, 18)])
        values = np.arange(34, dtype=np.float32) + 100
        valid = np.ones(34, bool); valid[17 + 11] = False
        top, bottom = heater_values(names, values, valid)
        self.assertTrue(np.array_equal(top, values[:17]))
        self.assertTrue(np.isnan(bottom[11]))
        self.assertEqual(float(bottom[16]), 133.0)

    def test_interpolation_fills_internal_nans_without_edge_extrapolation(self):
        raw = np.asarray([np.nan, 10., np.nan, np.nan, 40., np.nan], np.float32)
        filled, imputed = interpolate_between_heaters(raw)
        self.assertTrue(np.isnan(filled[0]) and np.isnan(filled[-1]))
        self.assertTrue(np.allclose(filled[1:5], [10., 20., 30., 40.]))
        self.assertTrue(np.array_equal(imputed, [False, False, True, True, False, False]))

    def test_provisional_projection_uses_bounded_x_zones(self):
        cad = np.asarray([[0., 0., 0.], [5., 0., 0.], [10., 0., 0.]])
        top = np.arange(17, dtype=np.float32); bottom = top + 20
        zone, node_top, node_bottom, delta = provisional_heater_projection(cad, top, bottom)
        self.assertTrue(np.array_equal(zone, [0, 8, 16]))
        self.assertTrue(np.array_equal(node_top, [0, 8, 16]))
        self.assertTrue(np.array_equal(node_bottom, [20, 28, 36]))
        self.assertTrue(np.array_equal(delta, [-20, -20, -20]))

    def test_geodesic_area_follows_mesh_edges(self):
        edge = np.asarray([[0, 1, 1, 2], [1, 0, 2, 1]])
        length = np.asarray([2., 2., 3., 3.])
        self.assertTrue(np.allclose(geodesic_distance(3, edge, length, 0), [0, 2, 5]))

    def test_csv_point_does_not_invent_extent(self):
        with tempfile.TemporaryDirectory() as tmp:
            path = Path(tmp) / "defect.csv"
            with path.open("w", encoding="utf-8-sig", newline="") as stream:
                writer = csv.writer(stream); writer.writerow(["No", "X", "Y", "W", "H", "Error"])
                writer.writerow([1, 12, 34, "", "", "찍힘"])
            row = read_defect_csv(path)
        self.assertEqual(row["pixel_xy"], [12., 34.])
        self.assertIsNone(row["width_px"]); self.assertIsNone(row["height_px"])


if __name__ == "__main__":
    unittest.main()
