import matplotlib.pyplot as plt
import numpy as np
from shapely.geometry import Polygon, LineString, Point
from shapely.ops import split

# نقاط به صورت صریح (List of Tuples)
points = [
    (3277288.39, 636672.8600),
    (3277247.34, 636669.1633),
    (3277219.93, 636654.9200),
    (3277254.653, 636622.6312),
    (3277290.043, 636536.8892),  # P5
    (3277307.467, 636435.4220),
    (3277341.137, 636363.4741),
    (3277354.027, 636317.3670),
    (3277367.99,  636310.5000),  # P9
    (3277341.826, 636527.7171),
]

AREA_A = 4500.0   # قطعه اول از سمت P9
AREA_B = 2000.0   # انبار اول
AREA_C = 2000.0   # نوار جدید — فقط این هاشور می‌خورد

poly = Polygon(points)
p9 = np.array(points[8], dtype=float)
p5 = np.array(points[4], dtype=float)

axis = p5 - p9
u = axis / np.linalg.norm(axis)
v = np.array([-u[1], u[0]])
projs = (np.array(points, dtype=float) - p9) @ u
t_max = float(projs.max())


def cut_at(t: float):
    center = p9 + t * u
    L = 5000.0
    cutter = LineString([tuple(center - L * v), tuple(center + L * v)])
    parts = split(poly, cutter)
    p9_pt = Point(float(p9[0]), float(p9[1]))
    bottom = min(parts.geoms, key=lambda g: g.distance(p9_pt))
    cut_seg = poly.intersection(cutter)
    return bottom, cut_seg


def bottom_area(t: float) -> float:
    return cut_at(t)[0].area


def find_t_for_area(target: float) -> float:
    lo, hi = 0.0, t_max
    for _ in range(80):
        mid = (lo + hi) / 2.0
        if bottom_area(mid) < target:
            lo = mid
        else:
            hi = mid
    return (lo + hi) / 2.0


def cut_coords_of(cut_seg):
    if cut_seg.geom_type == "LineString":
        return list(cut_seg.coords)
    if cut_seg.geom_type == "MultiLineString":
        return list(max(cut_seg.geoms, key=lambda g: g.length).coords)
    return []


def plot_polygon(geom, **kwargs):
    if geom.is_empty:
        return
    if geom.geom_type == "Polygon":
        geoms = [geom]
    elif geom.geom_type == "MultiPolygon":
        geoms = list(geom.geoms)
    else:
        return
    for g in geoms:
        x, y = g.exterior.xy
        plt.fill(x, y, **kwargs)


# سه برش تجمعی: 4500 → 6500 → 8500
cum_a = AREA_A
cum_b = AREA_A + AREA_B
cum_c = AREA_A + AREA_B + AREA_C

t1 = find_t_for_area(cum_a)
t2 = find_t_for_area(cum_b)
t3 = find_t_for_area(cum_c)

poly_a, cut1 = cut_at(t1)          # 4500
poly_ab, cut2 = cut_at(t2)         # 6500
poly_abc, cut3 = cut_at(t3)        # 8500

zone_a = poly_a
zone_b = poly_ab.difference(poly_a)      # انبار اول 2000
zone_c = poly_abc.difference(poly_ab)    # نوار جدید 2000 — فقط هاشور

area_a = zone_a.area
area_b = zone_b.area
area_c = zone_c.area
coords1 = cut_coords_of(cut1)
coords2 = cut_coords_of(cut2)
coords3 = cut_coords_of(cut3)

# --- رسم ---
xs, ys = zip(*points)
xs_closed = list(xs) + [xs[0]]
ys_closed = list(ys) + [ys[0]]

plt.figure(figsize=(10, 8))
plt.plot(xs_closed, ys_closed, "b-o", linewidth=2, markersize=6, label="Polygon Boundary")
plt.fill(xs_closed, ys_closed, "skyblue", alpha=0.2)

# Zone A و B: بدون هاشور
plot_polygon(
    zone_a,
    facecolor="lightgray",
    edgecolor="gray",
    alpha=0.45,
    linewidth=1.0,
    label=f"Zone A = {area_a:.2f} m²",
)
plot_polygon(
    zone_b,
    facecolor="khaki",
    edgecolor="darkgoldenrod",
    alpha=0.45,
    linewidth=1.0,
    label=f"Anbar 1 = {area_b:.2f} m²",
)

# Zone C: فقط این هاشور
plot_polygon(
    zone_c,
    facecolor="salmon",
    edgecolor="darkred",
    alpha=0.45,
    hatch="xxx",
    linewidth=1.5,
    label=f"Zone C = {area_c:.2f} m²",
)

# خطوط برش
def draw_cut(coords, style, color, marker, label, prefix, offset):
    if not coords:
        return
    cx, cy = zip(*coords)
    plt.plot(cx, cy, style, color=color, linewidth=2.2, label=label)
    for i, (x, y) in enumerate(coords, 1):
        plt.plot(x, y, marker, markersize=6, color=color)
        plt.annotate(
            f"{prefix}{i}", (x, y),
            textcoords="offset points", xytext=offset,
            fontsize=8, color=color, fontweight="bold",
        )


draw_cut(coords1, "-", "black", "s", "Cut 1 (after 4500)", "A", (6, -12))
draw_cut(coords2, "-", "darkorange", "s", "Cut 2 (after +2000)", "B", (6, 6))
draw_cut(coords3, "-", "darkred", "s", "Cut 3 (after +2000)", "C", (6, -12))

for i, (x, y) in enumerate(points, 1):
    plt.annotate(
        f"P{i}", (x, y),
        textcoords="offset points", xytext=(5, 5),
        fontsize=9, fontweight="bold",
    )

# برچسب‌ها
for geom, text, edge in [
    (zone_a, f"{area_a:.1f} m²", "gray"),
    (zone_b, f"{area_b:.1f} m²", "darkgoldenrod"),
    (zone_c, f"Zone C\n{area_c:.1f} m²", "darkred"),
]:
    c = geom.centroid
    plt.annotate(
        text, (c.x, c.y),
        ha="center", va="center",
        fontsize=9, fontweight="bold" if "Zone C" in text else "normal",
        color="dimgray" if edge == "gray" else edge,
        bbox=dict(boxstyle="round,pad=0.25", facecolor="white", edgecolor=edge, alpha=0.9),
    )

plt.gca().set_aspect("equal", adjustable="box")
plt.title("4500 + 2000 + 2000 m² (only last 2000 hatched)", fontsize=14)
plt.xlabel("X Coordinate", fontsize=12)
plt.ylabel("Y Coordinate", fontsize=12)
plt.grid(True, linestyle=":", alpha=0.6)
plt.legend(loc="best")

out_name = "polygon_split_4500_2000_2000.png"
plt.savefig(out_name, dpi=200, bbox_inches="tight")

print("Total polygon area:", round(poly.area, 2), "m2")
print("Zone A:", round(area_a, 4), "m2")
print("Anbar 1:", round(area_b, 4), "m2")
print("Zone C (hatched):", round(area_c, 4), "m2")
print("t1:", round(t1, 3), "m | t2:", round(t2, 3), "m | t3:", round(t3, 3), "m")
for name, coords in [("Cut1", coords1), ("Cut2", coords2), ("Cut3", coords3)]:
    if coords:
        print(f"{name} endpoints:")
        for i, c in enumerate(coords, 1):
            print(f"  ({c[0]:.4f}, {c[1]:.4f})")
print("Success: Plot saved as", out_name)
try:
    plt.show()
except Exception:
    pass
